// ZIM Cat - Interactive Media Framework at https://zimjs.com - code creativity!
// Also see https://zimjs.com/distill to minify only the functions in your app
// (c) 2021 ZIM - free to use - donations welcome of course! https://zimjs.com/donate
// With thanks...
// Thanks to ZzFX - Zuper Zmall Zound Zynth - Micro Edition for play() method of Synth
// MIT License - Copyright 2019 Frank Force - https://github.com/KilledByAPixel/ZzFX
// Thanks to Josh Forisha - https://github.com/joshforisha for open-simplex-noise-js
// ZIM converted Noise() from https://www.npmjs.com/package/open-simplex-noise
// Thanks to Frank Los for coding the ZIM Keyboard()
// There are several dozen thanks through out the code as well - cheers!
// ZIM is written in ES5. We are aware of ES6 and ES6 modules.
// Here are reasons why we purposefully do not use ES6 and ES6 modules:
// https://github.com/danzen/zimjs/issues/38
// There is no problem using ZIM with ES6 code.
// The many CodePen examples are ES6 and a great place to start:
// https://codepen.io/topic/zim
// We are innovators and inventors at ZIM.
// We work for the people - for the creators
// to make your coding experience as wonderful as possible.
// Please see the MORE section on the following page for treats!
// It outlines UI/UX for end users but also for us, the coders:
// https://zimjs.com/uiux.html
// ZIM is a Framework and rarely needs to be used with
// Node, React, Angular, VUE, Animate, XYZ, etc.
// When it does, a zim namespace can be turned on if desired with zns=true.
// We have provided Node packages for ZIM and CreateJS, SHIM for Adobe,
// and help others on the SLACK at https://zimjs.com/slack (come join us!)
// integrate with "tag" mode into React and VUE, etc.
// but really, we would recommend you try ZIM on its own.
// It is just so easy to paste the template into a Text Editor and go.
// Leave all your outside worries behind and simply enjoy coding with ZIM!
// Let us handle the complexities as a scroll through the code will show! ;-)
// Cheers,
// Dr Abstract, Pragma and ZIM Team
// 2021
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ZIM CODE
// GLOBALS - may not be used if zns (ZIM namespace) is set to true
// If zns is false (default), then zimplify() will run and turn classes, functions and more constants global
// Thanks Stefan Meyer from Uruguay for the ESLint work
// global variable to hold default frame - used by other ZIM modules like physics, etc.
if (typeof window == "undefined") window = {};
var zimDefaultFrame = window.zimDefaultFrame;
var zdf = window.zdf; // short version as long version was starting to add up in minified code ;-)
var createjs = window.createjs; // the expected CreateJS namespace - import CreateJS first
var OPTIMIZE = window.OPTIMIZE;
var ACTIONEVENT = window.ACTIONEVENT;
var KEYFOCUS = window.KEYFOCUS;
var TIMECHECK = window.TIMECHECK;
var TIME = window.TIME;
var STYLE = window.STYLE;
var MOBILE = window.MOBILE;
var LOCALSTORAGE = window.LOCALSTORAGE;
var GET = window.GET;
var POST = window.POST;
var SOCKET = window.SOCKET;
var FIT = window.FIT;
var FILL = window.FILL;
var FULL = window.FULL;
var zimContactListener = window.zimContactListener;
var zimDefaultPhysics = window.zimDefaultPhysics;
var b2ContactListener = window.b2ContactListener;
var b2Vec2 = window.b2Vec2;
// INTRODUCTION
// The code is broken into modules that once were individually available.
// We then introduced ZIM Distill (tree-shaking) as a more efficient way to reduce code
// but we have kept the modules as follows:
// WRAP, CODE, DISPLAY, METHODS, CONTROLS, FRAME, META, and docs only: GAME, THREE, SOCKET, PIZZAZZ
// You can text search a bunch of ////... to get to these.
// The docs also have these modules but ordered differently
// FRAME, DISPLAY, METHODS, CONTROLS, CODE, WRAP, META, GAME, THREE, SOCKET, PIZZAZZ.
// Each entry in the Docs has a VIEW button at the bottom
// that will nicely display the code for that entry - from this document.
// So... there is perhaps, little need to be here ;-).
// The docs are created from the description in this document.
// https://zimjs.com/docs.html
// WARNING: the WRAP and the CODE module at the start here
// are not the focus of the ZIM Framework but rather helper functions
// and even some helper functions for DOM manipulation.
// You may want to skip ahead using //// with a space after to find your way ;-)
//////////////// ZIM WRAP //////////////
// Zim Wrap creates global wrapper functions for less typing
// set var zon=false before calling zim scripts to hide script comments
if (typeof zon == "undefined") var zon = true; // comments from zim scripts
if (typeof zns == 'undefined') var zns = false; // require zim namespace
/*--
zog(item1, item2, etc.) ~ log
zog
global function
DESCRIPTION
Short version of console.log()
to log the item(s) to the console.
Use F12 to open your Browser console.
zog is dedicated to Pragma (Madeline Zen) who was coding with Dr Abstract (Dan Zen) from the start
Also comes in six ZIM colors:
zogg("green");
zogp("pink");
zogb("blue");
zogr("red");
zogy("yellow");
zogo("orange");
Note: If zon (comments on) is set to false before ZIM runs, then all zog() commands are turned off
EXAMPLE
zog("hello", circle.x); // logs these values to the console
END EXAMPLE
PARAMETERS
item1, item2 (optional), etc. - items (expressions) to log to the console
RETURNS items it is logging separated by a space if more than one
--*///+0
// reported a bug in Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1280818
// that after FF 46 binding the console did not show file and line number
// this is fixed in FF 50 - quite the conversation this stirred
var zog = zon?console.log.bind(console):function(){};
// Thanks Ami and Yalon for the technique
var zogStyle = " border:thin solid black; color: black";
var zogg = zon?console.log.bind(console, "%c Z ", "background: #acd241;"+zogStyle):function(){};
var zogp = zon?console.log.bind(console, "%c Z ", "background: #e472c4;"+zogStyle):function(){};
var zogb = zon?console.log.bind(console, "%c Z ", "background: #50c4b7;"+zogStyle):function(){};
var zogr = zon?console.log.bind(console, "%c Z ", "background: #fb4758;"+zogStyle):function(){};
var zogy = zon?console.log.bind(console, "%c Z ", "background: #ebcb35;"+zogStyle):function(){};
var zogo = zon?console.log.bind(console, "%c Z ", "background: #f58e25;"+zogStyle):function(){};
var zogl = zon?console.log.bind(console, "%c Z ", "background: #eeeeee;"+zogStyle):function(){};
var zogd = zon?console.log.bind(console, "%c Z ", "background: #444444; border:thin solid black; color: white"):function(){};
//-0
/*--
zid(string) ~ id
zid
global function
DESCRIPTION
Short version of document.getElementById(string)
to access an HTML tag by its id.
EXAMPLE
zid("logo").addEventListener("click", function(){});
END EXAMPLE
PARAMETERS
string - the id of the tag you are wanting to access
RETURNS HTML tag with id of string or null if not found
--*///+1
function zid(s) {
z_d("1");
return document.getElementById(s);
} //-1
/*--
zss(string) ~ css
zss
global function
DESCRIPTION
Short version of document.getElementById(string).style
to access the style property of an HTML tag by the tag id.
EXAMPLE
zss("logo").margin = "10px";
END EXAMPLE
PARAMETERS
string - the id of the tag whose style you are wanting to access
RETURNS style property of HTML tag with id of string or undefined if not found
--*///+2
function zss(s) {
z_d("2");
if (document.getElementById(s)) {return document.getElementById(s).style;}
else if (zon) zogy("zss(): id not found");
} //-2
/*--
zgo(url, target, width, height, fullscreen, modal) ~ go
zgo
global function
DESCRIPTION
Short version of either window.location.href or window.open
to open a link in the same window or a specified window.
EXAMPLE
zid("logo").addEventListener("click", function(){zgo("https://zimjs.com");});
// with a ZIM object:
var button = new Button();
button.center();
button.on("click", function() {zgo("http://zimjs.com");});
END EXAMPLE
PARAMETERS
url - the link to use (Absolute, Relative or Virtual)
target - (default null) the string name of a window (tab) _blank for new window each time
width - (default null) width of window (use with fullscreen true)
height - (default null) height of window (use with fullscreen true)
fullscreen - (default null) not really full screen but rather opens in a new window not tab
modal - (default false) set to true to force user to close window
RETURNS null if opening in same window or reference to the window otherwise
--*///+3
function zgo(u,t,w,h,f,m) {
z_d("3");
if ((zot(t) && t != "") || t == "_self") {
window.location.href = u;
} else {
var added = "";
if (w) added += "width=" + w + ",";
if (h) added += "height=" + h + ",";
if (f) added += "fullscreen=yes,";
if (m) added += "modal=yes,alwaysRaised=yes";
return window.open(u,t,added);
}
} //-3
/*--
zum(string) ~ num
zum
global function
DESCRIPTION
Takes the units off a string number.
Converts "10px" string from styles to number 10, for instance.
If there is no value then this will return 0.
EXAMPLE
// in HTML
LOGO
// in JavaScript
var left = zum(zss("logo").left); // converts 10px to the Number 10
left += 20; // adds 20 to 10
zss("logo").left = left + "px"; // assigns 30px to left style
END EXAMPLE
PARAMETERS
string - the string representation of a number eg. "10px"
RETURNS a Number
--*///+4
function zum(s) {
z_d("4");
if (zot(s)) return;
return Number(String(s).replace(/[^\d\.\-]/g, ''));
} //-4
/*--
zot(value) ~ not
zot
global function
DESCRIPTION
Test to see if value has no value (value must exist as var or parameter)
or if value has been set to null.
Good for setting function defaults.
Really just asking if the value == null.
Often we forget exactly how to do this - it is tricky:
value === null, value == undefined, value == 0, !value DO NOT WORK.
EXAMPLE
if (zot(width)) width = 100;
// equivalent to
if (width == null) width = 100;
END EXAMPLE
PARAMETERS
value - a variable or parameter you want to see if there is no value assigned
RETURNS Boolean true if value does not exist
--*///+4.5
function zot(v) {
return v==null; // both null and undefined match but not false or 0
}//-4.5
/*--
zop(e) ~ stop
zop
global function
DESCRIPTION
Stop event propagation to subsequently added existing listeners.
Must pass it e || window.event from your event function.
NOTE: this is not canceling the default action -
to cancel default action use e.preventDefault();
EXAMPLE
zid("button").addEventListener("click", function(e) {
// do something
zop(e||window.event);
});
END EXAMPLE
PARAMETERS
e - the event object from your event function
collect the event object as e and then pass in e || window.event
RETURNS null
--*///+5
function zop(e) {
z_d("5");
if (zot(e)) return;
if (e.stopImmediatePropagation) e.stopImmediatePropagation();
if (window.event) window.event.cancelBubble=true;
} //-5
/*--
zil() ~ still
zil
global function
DESCRIPTION
Stop keys from moving content - arrows, spacebar, pgup, pgdown, home, end.
Stop scroll wheel from moving content - scrolling the canvas for instance.
ZIM Frame does this in the full, fit and outside scale modes.
If not using Frame, then you can do this once at the start of your code.
Returns an array of references to three listeners: [keydown, wheel and DOMMouseScroll].
Use these to removeEventListeners.
The arrows, etc, still work but just not their default window behaviour.
EXAMPLE
// at the top of your code
var listenersArray = zil();
// key and mousewheel arrows, spacebar, etc.
// will have their default actions stopped until you remove the listeners:
// window.removeEventListener("keydown", listenersArray[0]); // etc.
END EXAMPLE
RETURNS an Array
--*///+6
function zil() {
z_d("6");
var a = function(e) {if (!e) e = event; if (e.keyCode && (e.keyCode >= 32 && e.keyCode <= 40)) e.preventDefault();};
var b = function(e) {if (!e) e = event; e.preventDefault();};
var c = b;
window.addEventListener("keydown", a, {passive:false});
window.addEventListener("wheel", b, {passive:false});
window.addEventListener("DOMMouseScroll", c, {passive:false});
return [a, b, c];
} //-6
/*--
zet(selector) ~ set
zet
global function
DESCRIPTION
Uses document.querySelectorAll() to get a list of tags.
Returns a ZIM Zet object which can be used to add events or styles to the set.
EXAMPLE
zet(".class").on("click", function(){}); // would add function event to all tags with the class
zet("p").css("color", "goldenrod"); // would make the text of all paragraphs goldenrod
zet("#test").css({color:"red", "background-color":"blue", paddingLeft:"20px"});
// set a custom open property on all section bars to false
zet("section .bar").prop("open", false);
// set the custom open property on all section bars to true and set the innerHTML to CLOSE
zet("section .bar").prop({open: true, innerHTML: "CLOSE"});
END EXAMPLE
PARAMETERS
selector - a CSS query selector such as a class, id, tag, or multiple selectors separated by commands
can also be complex selectors suchs as ".class img"
METHODS (on the returned Zet object)
zet(selector).on(type, function) - a shortcut for addEventListener() and will be added to all tags matching the selector
zet(selector).off(type, function) - a shortcut for removeEventListener() and will be remove from all tags matching the selector
zet(selector).css(property, value) - gets and sets styles
- gets the first programmatic property if a single string property is passed
- sets the property to the value on each of the Zet's tags from the selector passed to zet()
- if an object of properties and values is passed as the single parameter then sets all these properties
- NOTE: style names do not need quotes unless the dash is used - so camelCase does not require quotes
- NOTE: remember that commas are used for objects - not the semi-colon as in CSS
zet(selector).prop(property, value) - gets or sets a property on a set of tags
- if an object of properties and values is provided as a single parameter, then sets all these on the set
- else if no value is set then returns an array of the set tags values for the property
- else if value is a single value then sets the property of the tags in the set to the value
PROPERTIES (on the returned Zet object)
tags - an HTML NodeList tag list
RETURNS Zet object with on(), off(), css() methods and tags property (NodeList tag list)
--*///+6.1
function zet(selector) {
z_d("6.1");
function Zet() {
var that = this;
this.on = function(type, call) {
if (zot(selector) || zot(type) || zot(call)) return;
var tags = that.tags;
for (var i=0; ib or a.5) {a*=-1; b*=-1;}
if (integer) if (a>b) {a++;} else if (b>a) {b++;}
var r;
if (a == 0 && b == 0) return 0;
else if (b == 0) r = Math.random()*a;
else r = Math.min(a,b) + Math.random()*(Math.max(a,b)-Math.min(a,b));
if (integer) return Math.floor(r);
else return r;
};//-9
/*--
zim.series = function(array|item1|obj, item2, item3)
series
zim function
DESCRIPTION
Returns a function that will return each value passed as a parameter (or an Array) in order
or an object literal with min and max.
This goes in sequence each time the function is called.
Use this to pass a series in to any ZIM VEE value so a looping series is obtained.
NOTE: was called makeSeries() which is now depricated
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// note - do not call the variable name series
var colors = series(red, green, blue);
colors(); // red
colors(); // green
colors(); // blue
colors(); // red, etc.
// or
var colors = [red, green, blue];
var s = series(colors);
s(); // red
s(); // green
s(); // blue
s(); // red, etc.
new Tile(new Rectangle(10,10,[blue, red]), 10, 10); would randomize colors
new Tile(new Rectangle(10,10,series(blue, red)), 10, 10); would alternate colors
END EXAMPLE
EXAMPLE
STYLE = {color:series(pink, green, blue)}
loop(9, function (i) {
new Circle(100).loc(110+i*100, 400)
});
END EXAMPLE
EXAMPLE
// ten rectangles getting higher by 20 each time
var s = series({min:10, max:200}).step(20);
loop(10, function (i) {
new Rectangle(10, s, red).sca(1,-1).loc(100+i*20, 400);
});
END EXAMPLE
EXAMPLE
// added functionality as of ZIM 10.9.0
// start at index 3, reverse and don't go past 0
var nums = series(0, 1, 2, 3, 4).jump(3).reverse().constrain();
loop(5, function(){
zogb(nums()); // 3,2,1,0,0 (blue in console)
});
nums.reverse(false); // go forward - note, still starting at index 0
zogg(nums()); // 0 (green in console)
zogg(nums()); // 1
zogg(nums()); // 2
nums.bounce(); // go back and forth rather than default loop
loop(5, function(){
zogy(nums()); // 3,4,3,2,1 (yellow in console)
});
nums.step(3); // sitting at 0 then increase the step to 3
loop(5, function(){
zogr(nums()); // 0,3,2,1,4 (red in console)
// 3->6 bounces off 4 with two back to 2
// 2->-1 bounces off 0 with one forward to 1
// tricky but correct
});
zogp(nums.index); // 1 - coming back 3 steps from 4 to 1 as current index
END EXAMPLE
PARAMETERS
array|item1|{min,max,step} - the first item - or an array of results that will be called in order as the resulting function is called
or an object with min, max and step properties to make a series of numbers from and including min and max (step defaults to 0)
this will make an array of values and then it is just like an array was entered initially.
when used with ZIM VEE - the values may be further ZIM VEE values (including more series values)
item2 - the second item if the first is not an array
item3 - the third item, etc. to as many items as needed
METHODS
step(num) - num defaults to 1 - the number of items to move the index - or use index property
every(num) - num defaults to 0 - steps to wait before moving to the next index - remain on blue for five, then go to yellow for five, etc.
jump(index) - jump to an index but do not run it - the next call to the series will run here
reverse(boolean) - boolean defaults to true - reverses direction - or pass in false to cancel reverse
bounce(boolean) - boolean defaults to true - back and forth between 0 and length-1 - or pass in false to cancel bounce
constrain(boolean) - boolean defaults to true - keeps index between 0 and length-1 - or pass in false to cancel constrain
PROPERTIES
array - an array of items passed in to the function
length - the length of the series
index - get or set the current index of the series - what will run next
RETURNS a function that can be called many times - each time returning the next value in the series
--*///+13.61
zim.series = function() {
z_d("13.61");
var array;
var range;
if (arguments.length == 0) return function(){};
if (arguments.length == 1 && Array.isArray(arguments[0])) {
array = arguments[0];
} else if (arguments.length == 1 && arguments[0].constructor == {}.constructor) {
range = arguments[0];
if (zot(range.min)) range.min = 0;
if (zot(range.max)) range.max = 1;
if (zot(range.step)) range.step = 1;
array = [];
zim.loop(Math.floor(Math.abs(range.max-range.min)+range.step), function (i) {
array.push(i+range.min);
}, null, range.step);
range = null;
} else {
array = Array.prototype.slice.call(arguments);
}
var count = 0;
var dir = 1;
var step = 1;
var every = 0;
var everyCount = 0;
var bounce = false;
var constrain = false;
var lastVal;
var f = function() {
if (every && everyCount%(every) != 0) {
everyCount++;
return lastVal;
}
everyCount++;
var length = array.length;
var val;
val = array[(length*10+count)%length];
if (bounce) {
if (dir > 0 && count+dir*step >= length) {
dir = -1;
count = (length-1)-(count+step-(length-1));
} else if (dir < 0 && count+dir*step < 0) {
dir = 1;
count = step - count;
} else {
count += dir*step;
}
} else if (constrain) {
if (dir > 0 && count+dir*step >= length) count = length-1;
else if (dir < 0 && count+dir*step < 0) count = 0;
else count += dir*step;
} else {
count += dir*step;
}
lastVal = val;
return val;
};
f.array = array;
f.type = "series";
Object.defineProperty(f, 'index', {
get: function() {
var length = array.length;
return (length*10+count)%length;
},
set: function(value) {
count = value;
}
});
f.jump = function(value) {
count = value;
return f;
};
f.reverse = function(value) {
if (zot(value)) value = true;
if (value) dir = -1;
else dir = 1;
count = array.length-1;
return f;
};
f.bounce = function(value) {
// normalize count
if (zot(value)) value = true;
var length = array.length;
count = (length*10+count)%length;
bounce = value;
return f;
};
f.step = function(value) {
if (zot(value)) value = 1;
step = Math.floor(value);
return f;
};
f.every = function(value) {
if (zot(value)) value = 1;
every = Math.abs(value);
everyCount = 0;
return f;
};
f.constrain = function(value) {
if (zot(value)) value = true;
constrain = value;
return f;
};
return f;
};//-13.61
/*--
zim.makeSeries = function(array)
depreciated - use series()
--*///+13.6
zim.makeSeries = function(array) {
z_d("13.6");
if (zot(array)) return function(){};
var count = 0;
var f = function() {
return array[(count++)%array.length];
};
f.array = array;
return f;
};//-13.6
/*--
zim.loop = function(obj, call, reverse, step, start, end)
loop
zim function
DESCRIPTION
1. If you pass in a Number for obj then loop() does function call that many times
and passes function call the currentIndex, totalLoops, startIndex, endIndex, obj.
By default, the index starts at 0 and counts up to one less than the number.
So this is like: for (var i=0; i6) return "break"; // quit loop when > 6
zog(i);
});
loop(10, function(i) {
zog(i); // 9-0 in console
}, true);
loop(10, function (i) {
zog(i); // 5-9
}, null, 1, 5)
// the start parameter cannot be less than 0
// to get negative values for i subtract a desired value inside the loop
var colors = [green, yellow, pink];
loop(colors, function(color, index, start, end, array) { // do not have to collect all these
zog(color); // each color
});
var array = [0,0,0,1,0,0,0];
var pass = loop(array, function(val) {
if (val!=0) return false;
});
// below will log failed
if (pass) zog("passed"); // by default loop returns true (as of ZIM 10.6.1)
else zog("failed"); // false inside loop gets assigned to pass
var person = {name:"Dan Zen", occupation:"Inventor", location:"Dundas"}
var result = loop(person, function(prop, val, index, total, start, end, object) { // do not have to collect all these
zog(prop, val); // each key value pair
if (val == "criminal") return "criminal"; // this would return out of the loop to the containing function
});
if (result == "criminal") alert("oh no!");
var tags = zet(".heading").tags; // get an NodeList of tags styled with heading class
loop(tags, function(tag, i) {
tag.innerHTML = i + ". " + tag.innerHTML; // add an index number in front
});
END EXAMPLE
PARAMETERS supports DUO - parameters or single object with properties below
obj - a Number of times to loop or an Array or Object, String or NodeList to loop through
call - the function to call
the function will receive (as its final parameters) the index, total, start, end, obj
where the index is the current index, total is how many times the loop will run
start is the start index, end is the end index and obj is the object passed to the loop
the starting parameters vary depending on the type of obj:
if the obj is a number then the first parameter is the index (no extra starting parameters given)
if the obj is an array then the first parameter is the element at the current index
if the obj is an object literal then the first and second parameters are the property name and property value at the current index
if the obj is an string then the first parameter is the letter
if the obj is an HTMLCollection then the first parameter is the tag
reverse - (default false) set to true to run the loop backwards to 0
step - (default 1) each step will increase by this amount (positive whole number - use reverse to go backwards)
start - (default 0 or length-1 for reverse) index to start
end - (default length-1 or 0 for reverse) index to end
RETURNS any value returned from the loop - or true if no value is returned from a loop
--*///+9.5
zim.loop = function(obj, call, reverse, step, start, end) {
var sig = "obj, call, reverse, step, start, end";
var duo; if (duo = zob(zim.loop, arguments, sig)) return duo;
z_d("9.5");
if (zot(obj) || zot(call)) return undefined;
if (zot(reverse)) reverse = false;
if (zot(step) || step <= 0) step = 1;
var type = typeof obj=="number"?"number":(obj.constructor === Array?"array":(obj.constructor === {}.constructor?"object":(typeof obj == "string"?"string":(obj instanceof NodeList?"nodelist":(obj instanceof HTMLCollection?"htmlcollection":"invalid")))));
if (type == "invalid") {
return undefined;
}
if (type == "number" || type == "string" || type == "array" || type == "nodelist" || type == "htmlcollection") {
var length = type=="number"?obj:obj.length;
var total = getTotal(length-1);
if (total == 0) return true;
if (reverse) {
for(var i=start; i>=end; i-=step) {
var r;
if (type=="number") {
r = call(i, total, start, end, obj);
} else if (type=="array" || type=="string") {
r = call(obj[i], i, total, start, end, obj);
} else { // nodelist
r = call(obj.item(i), i, total, start, end, obj);
}
if (typeof r != 'undefined') return r;
}
} else {
for(var i=start; i<=end; i+=step) {
var r;
if (type=="number") {
r = call(i, total, start, end, obj);
} else if (type=="array" || type=="string") {
r = call(obj[i], i, total, start, end, obj);
} else { // nodelist or htmlcollection
r = call(obj.item(i), i, total, start, end, obj);
}
if (typeof r != 'undefined') return r;
}
}
return true;
} else if (type == "object") {
var length = 0;
var props = [];
for (var i in obj) {
length++;
props.push(i);
}
var total = getTotal(length-1);
if (total == 0) return;
if (reverse) {
for(var i=start; i>=end; i-=step) {
var r = call(props[i], obj[props[i]], i, total, start, end, obj);
if (typeof r != 'undefined') return r;
}
} else {
for(var i=start; i<=end; i+=step) {
var r = call(props[i], obj[props[i]], i, total, start, end, obj);
if (typeof r != 'undefined') return r;
}
}
return true;
}
function getTotal(max) {
if (zot(start)) start = reverse?max:0;
if (zot(end)) end = reverse?0:max;
if ((reverse && end > start) || (!reverse && start > end)) return 0;
if ((start < 0 && end) <0 || (start > max && end > max)) return 0;
start = Math.max(0, Math.min(start, max));
end = Math.max(0, Math.min(end, max));
return Math.floor((reverse?(start-end):(end-start)) / step) + 1;
}
};//-9.5
/*--
getTIME = function(time, timeType, minWarning, maxWarning, noWarning)
getTIME
global function
Checks for TIME and timeUnit
Used internally by interval, timeout, animate and others
returns the time unit as "s" or "m"
~~~~~~~~~~~~~~
checkTIME = function(time, timeChar, minWarning, maxWarning)
checkTIME
globalFunction
Tests to see if time is in expected units - timeChar is "s" or "m" for seconds or milliseconds
logs a warning if ((timeChar="s" && time>minWarning) || (timeChar=="m" && timeminWarning) || (timeChar=="m" && time= time) {
obj.done = true;
(call)(obj);
obj.clear();
return;
}
obj.rid = requestAnimationFrame(next);
}
obj.pause = function(state, immediate, reset) {
if (zot(state)) state = true;
if (state) { // pausing
cancelAnimationFrame(obj.rid);
} else { // unpausing
if (immediate) lastTime = 0; // a long time ago ;-)
else if (reset) {lastTime = Date.now(); obj.time=0;}
else lastTime = Date.now();
next();
}
obj.paused = state;
};
obj.clear = function() {
if (obj) cancelAnimationFrame(obj.rid);
for (var i in obj) {
delete obj[i];
}
obj.pause = function() {};
obj.clear = function() {};
};
next(); // thanks StevenWarren for the glitch fix!
return obj;
};//-9.7
/*--
zim.interval = function(time, call, total, immediate, pauseOnBlur, timeUnit)
interval
zim function
DESCRIPTION
Calls a function after each time delay - like window.setInterval().
Can pass in an Array of two times to set random time delays each interval.
Can pass in how many times you want to run the function and whether it runs right away.
NOTE: as of ZIM Cat time is in seconds not milliseconds.
Set TIME = "milliseconds"; to set all ZIM time to milliseconds
or pass in "milliseconds" to the timeUnit parameter for a specific override.
NOTE: setInterval has the time parameter last, interval has it first
so that it is consistent with loop() and the CreateJS on() method
NOTE: to clear a interval you use intervalObj.clear() - different than window.clearInterval(returnID)
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
interval(1, function(){
circle.x += 100;
stage.update();
});
// every second the circle will move 100 pixels
// if you want smooth movement, use:
Ticker.add(function() {
circle.x += 100; // no need for stage.update()
});
interval(1, function(obj) {
zog("counting " + obj.count); // starts counting at 1
if (obj.count == 10) obj.clear(); // will now log 1 to 10
});
OR better:
interval(1, function(obj) {
zog("counting " + obj.count); // starts counting at 1
}, 10); // now will log 1 - 10 with total parameter set to 10
IMMEDIATE:
interval(1, function(obj) {
zog("counting " + obj.count); // starts counting at 0
}, 10, true); // now will log 0 - 9 with immediate parameter set to true
EXTERNAL control:
var interval = interval(1, function() {
zog("counting " + interval.count); // starts counting at 1
});
var button = new Button({label:"STOP", toggle:"START"}).center();
button.on("click", function(){interval.pause(button.toggled);});
RANDOM intervals with ZIM Pick() literals
interval({min:.2, max:.8}, dropBombs); // bombs will fall at different rates between 200ms and 800ms
interval([1, 2], dropBombs); // bombs will fall at either 1 or 2 s
var count = 1;
function increase() {return ++count}
interval(increase, dropBombs); // bombs will fall at 1 second, then again after 2 more seconds and 3 seconds more after that, etc.
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
time - |ZIM VEE| (default 1) seconds for the interval (delay until the function runs - again and again)
see TIME global constant (defaults to "seconds") can also override with timeUnit parameter set to "milliseconds"
call - function to call when the interval passes
Will be passed a ZIM intervalObject as a single parameter
This is the same as the return object from animate()
See the Returns section below for methods and properties of the intervalObject
total - (default null - infinite) the number of times the function is called
note: the count property counts intervals but the total property is based on function calls.
The total will be equal to the end count with the immediate parameter set to false (default)
but the total will be one less than the count if the immediate parameter is true (like an Array index and length)
immediate - (default false) set to true to call the function right away (and then still call every interval)
This will not increase the count in the intervalObject because count counts intervals not function calls
Use the provided parameter of the call function to access the intervalObject inside the call function
pauseOnBlur - (default false) set to true to pause interval when window is reduced or another tab gains focus
timeUnit - (default seconds) set to "milliseconds" for traditional JavaScript milliseconds
also see TIME constant which defaults to "seconds"
timeUnit will override the TIME constant
RETURNS a ZIM intervalObject to pause and clear the interval with the following methods and properties:
METHODS - of ZIM intervalObject
pause(state, immediate, reset) - (default true) will pause the interval - set to false to unpause the interval with time left
immediate (default false) set to true to make the interval function run right away when unpausing (no effect when pausing)
reset (default false) set to true to set the interval back to 0 time passed when unpausing (no effect when pausing)
clear() - will clear the interval
PROPERTIES - of ZIM intervalObject
time - |ZIM VEE| get or set the time for the interval (see time parameter)
count - get the number of times the interval has run (if immediate is true, the first count is 0)
total - get or set the number of times the interval will run if the total parameter is set - otherwise -1 for infinite
paused - get the paused state of the interval (see pause() method)
pauseTimeLeft - if paused, get how much time is left once unpaused
--*///+9.8
zim.interval = function(time, call, total, immediate, pauseOnBlur, timeUnit) {
var sig = "time, call, total, immediate, pauseOnBlur, timeUnit";
var duo; if (duo = zob(zim.interval, arguments, sig, this)) return duo;
z_d("9.8");
if (zot(call)) return;
if (typeof call != 'function') return;
var timeType = getTIME(time, timeUnit);
if (zot(time)) time = timeType=="s"?1:1000;
if (zot(immediate)) immediate = false;
if (!zot(total) && (isNaN(total) || total<=0)) return;
if (zot(total)) total = -1;
var obj = {count:0, total:total, paused:false, time:time, active:true, timeUnit:timeUnit};
if (pauseOnBlur) {
if (zot(zim.blurCheck)) zim.setBlurDetect();
zim.pauseOnBlur.push(obj);
}
function interval() {
obj.startTime = Date.now();
obj.interval = zim.Pick.choose(obj.time);
obj.id = setTimeout(function() {
if (obj.paused) return;
if (!obj.active) return;
// obj.rid = requestAnimationFrame(interval);
obj.count++;
(call)(obj);
interval();
checkTotal();
}, obj.interval*(timeType=="s"?1000:1));
}
if (immediate) {
setTimeout(function() {
(call)(obj);
checkTotal();
}, 10);
}
function checkTotal() {
if (total == -1) return;
if (obj.count >= (immediate?obj.total-1:obj.total)) obj.clear();
}
var pausedTimeout;
obj.pause = function(state, immediate, reset) {
if (zot(state)) state = true;
if (state) { // pausing
clearTimeout(pausedTimeout);
clearTimeout(obj.id);
cancelAnimationFrame(obj.rid);
obj.pauseTimeLeft = obj.interval-(Date.now()-obj.startTime)/(timeType=="s"?1000:1);
} else { // unpausing
if (!obj.paused) obj.pause(true);
pausedTimeout = setTimeout(function() {
obj.count++;
(call)(obj);
interval();
checkTotal();
}, immediate?0:(reset?obj.interval:obj.pauseTimeLeft)*(timeType=="s"?1000:1));
obj.pauseTimeLeft = null;
}
obj.paused = state;
};
obj.clear = function() {
obj.active = false;
clearTimeout(pausedTimeout);
cancelAnimationFrame(obj.rid);
clearTimeout(obj.id);
var count = obj.count;
for (var i in obj) {
delete obj[i];
}
obj.active = false;
obj.count = count;
obj.pause = function() {};
obj.clear = function() {};
};
interval();
return obj;
};//-9.8
/*--
zim.async = function(url, callback, callbackString, maxTime, maxCancel)
async
zim function
DESCRIPTION
A way to send data back and forth to a server script without reloading the HTML page.
(like AJAX but without the bother)
Uses a dynamic script call with an optional callback (cross domain calls are okay)
also known as JSON-P pattern but JSON is unnecessary - note, no JSON in two of the examples below.
Pass a url to the server script (ie. php or node page)
and an optional callback function that you define in your code (cannot be an anonymous function).
async will automatically add a random number to the end of your script call to defeat cache.
NOTE: async uses GET so data is limited to GET length (as of ZIM 10 - this is 2K to 8K depending on Browser)
If more data is required, use an AJAX library
NOTE: async uses an r CGI key to send a random number to defeat cache.
Do not send an r property
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// existing JSONp service:
// assuming that we have a callback function called test as shown below
async("http://ip-api.com/json?callback=async.test",test);
function test(data) {zog(data.country);}
// note that the callback we pass the service is async.test not just test
// this allows zim to handle scope issues and garbage collect the dynamic script when done
END EXAMPLE
EXAMPLE
// existing JSON service:
// if the service just returns JSON - then pass through a JSONp wrapper:
var api = "https://zimjs.com/codepen/ranker.php"; // not JSONp - just JSON
async("https://zimjs.org/cdn/jsonp.php?api="+api+"&callback=async.getData", getData);
function getData(data) {
zog(data); // data will be the JSON parsed object
}
See a full example here: https://codepen.io/danzen/pen/gNKQYY
Here is the jsonp.php code if you would like to host:
END EXAMPLE
EXAMPLE
// CLIENT - your own server script:
// assuming we have a callback function called myFunction as shown below
async("http://yourserver.com/script.php?id=72&name=dan", myFunction);
function myFunction(data){zog(data);}
// SERVER - your script must output the following format as a string:
// "async.myFunction(somedata)"
// in the php file we would use:
header('Content-type: text/javascript');
echo "async.myFunction('success')";
// to return an object literal with nodejs express for example, you would use:
res.send('async.myFunction({list:[1,2,3], name:"whatever"})');
// the data parameter in the myFunction function defined earlier would be an object literal
// we could then do zog(data.list[0]) to log the value 1, etc.
END EXAMPLE
PARAMETERS
url - url to the server script (ie. php or node page)
Note: async uses an r CGI key to send a random number to defeat cache - do not send an r property
callback - (default null) callback function that you define in your code (cannot be an anonymous function)
callbackString - (default null) a string name matching the function in case the file is minified
maxTime - (default 2 seconds) how long to wait for server response before triggering an error
may still trigger callback if callback comes later unless maxCancel is set to true
see also ZIM TIME constant
If maxTime is up without calling back the function
async will return two arguments to the callback function:
"asyncError" and either "timeout" or "cancelled"
maxCancel - (default false) set to true to have maxTime cancel a late callback response
calling the return function on async does two things:
1. it handles scope issues so we can find your callback function
2. it handles garbage collection to remove the dynamic script tag that was used
if you do not specify a callback function then just send "" back from your server script
NOTE: we have experienced duplicate script calls if nothing is sent back
NOTE: if more than one async() with the same named call function is run at the same time
then a queue of callbacks is created
if the data comes back in a different order, the wrong call could be called
if there is danger of this happening (rare) then use ZIM Ajax
RETURNS undefined
--*///+29
zim.async = function (url, callback, callbackString, maxTime, maxCancel) {
z_d("29");
if (zot(url)) return;
var tag = document.createElement("script");
var timeType = getTIME(maxTime);
if (zot(maxTime)) maxTime = timeType=="s"?2:2000;
if (callback) {
if (callbackString) var n = callbackString;
else var n = callback.toString().split(/\n/,1)[0].match(/^function\s?([^\s(]*)/)[1];
// create a queue if more than one async() to same callback function name
// if data is not returned in same order made, the wrong callbacks may be called
if (!zim.asyncList) zim.asyncList = {};
if (!zim.asyncList[n]) zim.asyncList[n] = [];
zim.asyncList[n].push(callback);
// create callback bridge on async function object
zim.async[n] = function() { // closure to access tag on callback bridge
var t = tag;
// var name = n;
var cancelMe = false;
var errorID = setTimeout(function(){
cancelMe = maxCancel;
if (typeof callback == "function") callback("asyncError", maxCancel?"cancelled":"timeout");
}, maxTime*(timeType=="s"?1000:1));
return function(d){
clearTimeout(errorID);
if (zim.asyncList[n]) callback = zim.asyncList[n].shift();
if (typeof callback == "function" && !cancelMe) callback(d);
// remove the script tag
if (t) t.parentNode.removeChild(t); t = null;
};
}();
} else {
if (zim.async.z_s && zim.async.z_s.parentNode) zim.async.z_s.parentNode.removeChild(zim.async.z_s); // keep overwriting same script tag if no callback
zim.async.z_s = tag;
}
if (!url.match(/\?/)) url += "?";
tag.setAttribute("src", url + "&r="+Math.random());
document.getElementsByTagName("head")[0].appendChild(tag);
};//-29
//
/*--
zim.couple = function(json)
couple
zim function
DESCRIPTION
Turns a nested JSON object into a single layer JSON object
The object will have _ between the id and the property name
eg. {"circle":{"x":"10", "y":"20"},"count":{"currentValue":"0"}}
is: {"circle_x":"10", "circle_y":"20", "count_currentValue":"0"}
This allows data to be JSON decoded on the server
and put more directly into table fields of the database
See also ZIM decouple()
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// note the two levels of nesting - this is the format of ZIM Bind data for instance
var test = JSON.stringify({circle:{x:10, y:20},count:{currentValue:0}});
zog(couple(test)); // {"circle_x":"10", "circle_y":"20", "count_currentValue":"0"}
END EXAMPLE
PARAMETERS
json - a JSON string in the nested form of:
{"obj1":{"prop1":"val", "prop2":"val"},"obj2":{"prop3":"val"}}
RETURNS a JSON string with one less level of objects in form of:
{"obj1_prop1":"val", "obj1_prop2":"val", "obj2_prop3":"val"}
--*///+29.2
zim.couple = function (json) {
z_d("29.2");
if (!zim.isJSON(json)) return json;
var obj = JSON.parse(json);
var obj2 = {};
for (var i in obj) {
var o = obj[i];
for (var j in o) {
obj2[i+"_"+j] = o[j];
}
}
return JSON.stringify(obj2);
};//-29.2
/*--
zim.decouple = function(json)
decouple
zim function
DESCRIPTION
Turns a flat coupled JSON object into a nested layer JSON object
The object will remove _ from between the id and the property name
eg. {"circle_x":"10", "circle_y":"20", "count_currentValue":"0"}
is: {"circle":{"x":"10", "y":"20"},"count":{"currentValue":"0"}}
This allows data from table fields of the database
to be more easily dealt with as objects with their own properties
See also ZIM couple()
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// note the two levels of nesting - this is the format of ZIM Bind data for instance
var test = {circle:{x:10, y:20},count:{currentValue:0}};
var test2 = JSON.stringify(test);
var test3 = couple(test);
// {"circle_x":"10", "circle_y":"20", "count_currentValue":"0"}
// send this to server to store in fields
// receive back similar coupled data from fields
// decouple the data:
var test4 = decouple(test3);
// {"circle":{"x":"10", "y":"20"},"count":{"currentValue":"0"}}
var test5 = JSON.parse(test4); // similar object to test!
// {circle:{x:10, y:20},count:{currentValue:0}};
END EXAMPLE
PARAMETERS
json - a JSON string in the coupled form of
{"obj1_prop1":"val", "obj1_prop2":"val", "obj2_prop3":"val"}
RETURNS a JSON string with one less level of objects in the form of:
{"obj1":{"prop1":"val", "prop2":"val"},"obj2":{"prop3":"val"}}
the original JSON string will be returned if the initial JSON string is not coupled
--*///+29.3
zim.decouple = function (json) {
z_d("29.3");
if (!zim.isJSON(json)) return json;
var obj = JSON.parse(json);
var obj2 = {};
for (var i in obj) {
var n = i.split("_", 2);
if (n.length != 2) return json;
if (!obj2[n[0]]) obj2[n[0]] = {};
obj2[n[0]][n[1]] = obj[i];
}
return JSON.stringify(obj2);
};//-29.3
/*--
zim.convertColor = function(color, toColorType, alpha)
convertColor
zim function
DESCRIPTION
Converts color to HEX numbers - for example: "#333333"
Or converts color to HTML string - for example: "red"
Or converts color to RGB - for example: "rgb(0,0,0)"
Or converts color to RGBA - for example: "rgba(0,0,0,.5)"
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var color = convertColor("red"); // result is "#ff0000"
var color = convertColor("rgb(255,0,0)")); // result is "#ff0000"
var color = convertColor("rgb(0,0,255)", "string"); // result is "blue"
var color = convertColor("rgb(0,0,20)", "string"); // result is "#000014" - no matching string color
var color = convertColor("#ff0000", "string"); // result is "red"
var color = convertColor("f00", "string"); // result is "red" - note missing # okay and can use three digits
var color = convertColor(blue, "rgba", .5); // result is "rgba(80,196,183,0.5)"
var color = convertColor("rgb(256,256,0)", "rgba", .3); // result is "rgba(256,256,0,.3)"
var color = convertColor("rgba(0,0,0,.2)", anyType, .5); // result is "rgba(0,0,0,.5)"
var color = convertColor("red", "hexNumber"); // result is 0xff0000
END EXAMPLE
PARAMETERS
color - (default black) the HTML string or HEX color (case insensitive)
"rgba()" to HEX will ignore alpha
toColorType - (default "hex") or use "string", "rgb", "rgba", "zim", "hexNumber"
if "string" and color does not match existing HTML string color
then will return HEX number as string
zim will convert zim rgb to zim string like "blue"
hexNumber is 0xff0000 in format
alpha - (default 1) the alpha used for the "rgba" toColorType
RETURNS a String with the converted color
--*///+27.5
zim.convertColor = function(color, toColorType, alpha) {
if (!zim.convertColorCheck) {z_d("27.5"); zim.convertColorCheck=true;}
if (zot(toColorType)) toColorType = "hex";
if (zot(color)) return;
color = zik(color);
var colors = ['black','aliceblue','antiquewhite','aqua','aquamarine','azure','beige','bisque','blanchedalmond','blue','blueviolet','brown','burlywood','cadetblue','chartreuse','chocolate','coral','cornflowerblue','cornsilk','crimson','cyan','darkblue','darkcyan','darkgoldenrod','darkgray','darkgrey','darkgreen','darkkhaki','darkmagenta','darkolivegreen','darkorange','darkorchid','darkred','darksalmon','darkseagreen','darkslateblue','darkslategray','darkslategrey','darkturquoise','darkviolet','deeppink','deepskyblue','dimgray','dimgrey','dodgerblue','firebrick','floralwhite','forestgreen','fuchsia','gainsboro','ghostwhite','gold','goldenrod','gray','grey','green','greenyellow','honeydew','hotpink','indianred','indigo','ivory','khaki','lavender','lavenderblush','lawngreen','lemonchiffon','lightblue','lightcoral','lightcyan','lightgoldenrodyellow','lightgray','lightgrey','lightgreen','lightpink','lightsalmon','lightseagreen','lightskyblue','lightslategray','lightslategrey','lightsteelblue','lightyellow','lime','limegreen','linen','magenta','maroon','mediumaquamarine','mediumblue','mediumorchid','mediumpurple','mediumseagreen','mediumslateblue','mediumspringgreen','mediumturquoise','mediumvioletred','midnightblue','mintcream','mistyrose','moccasin','navajowhite','navy','oldlace','olive','olivedrab','orange','orangered','orchid','palegoldenrod','palegreen','paleturquoise','palevioletred','papayawhip','peachpuff','peru','pink','plum','powderblue','purple','rebeccapurple','red','rosybrown','royalblue','saddlebrown','salmon','sandybrown','seagreen','seashell','sienna','silver','skyblue','slateblue','slategray','slategrey','snow','springgreen','steelblue','tan','teal','thistle','tomato','turquoise','violet','wheat','white','whitesmoke','yellow','yellowgreen'];
var hex = ['000000','f0f8ff','faebd7','00ffff','7fffd4','f0ffff','f5f5dc','ffe4c4','ffebcd','0000ff','8a2be2','a52a2a','deb887','5f9ea0','7fff00','d2691e','ff7f50','6495ed','fff8dc','dc143c','00ffff','00008b','008b8b','b8860b','a9a9a9','a9a9a9','006400','bdb76b','8b008b','556b2f','ff8c00','9932cc','8b0000','e9967a','8fbc8f','483d8b','2f4f4f','2f4f4f','00ced1','9400d3','ff1493','00bfff','696969','696969','1e90ff','b22222','fffaf0','228b22','ff00ff','dcdcdc','f8f8ff','ffd700','daa520','808080','808080','008000','adff2f','f0fff0','ff69b4','cd5c5c','4b0082','fffff0','f0e68c','e6e6fa','fff0f5','7cfc00','fffacd','add8e6','f08080','e0ffff','fafad2','d3d3d3','d3d3d3','90ee90','ffb6c1','ffa07a','20b2aa','87cefa','778899','778899','b0c4de','ffffe0','00ff00','32cd32','faf0e6','ff00ff','800000','66cdaa','0000cd','ba55d3','9370db','3cb371','7b68ee','00fa9a','48d1cc','c71585','191970','f5fffa','ffe4e1','ffe4b5','ffdead','000080','fdf5e6','808000','6b8e23','ffa500','ff4500','da70d6','eee8aa','98fb98','afeeee','db7093','ffefd5','ffdab9','cd853f','ffc0cb','dda0dd','b0e0e6','800080','663399','ff0000','bc8f8f','4169e1','8b4513','fa8072','f4a460','2e8b57','fff5ee','a0522d','c0c0c0','87ceeb','6a5acd','708090','708090','fffafa','00ff7f','4682b4','d2b48c','008080','d8bfd8','ff6347','40e0d0','ee82ee','f5deb3','ffffff','f5f5f5','ffff00','9acd32'];
if (toColorType.toLowerCase() == "zim") {
var i = zim.colorsHex.indexOf(color);
if (i<0) return color;
return zim.colors[zim.colorsHex.indexOf(color)];
}
var answer;
if (answer = color.match(/rgba\((.*)\)/)) {
if (zot(alpha)) {
color = "rgb("+answer[1]+")"; // includes alpha but does not matter
} else {
var c = color.split(",");
c[3] = alpha+")";
return c.join(",");
}
}
function rgbToHex(rgb) {
var hex = Number(rgb).toString(16);
if (hex.length < 2) {
hex = "0" + hex;
}
return hex;
}
function getRGB(string) {
var c = string.split(",");
var red = rgbToHex(c[0]);
var green = rgbToHex(c[1]);
var blue = rgbToHex(c[2]);
return [red, green, blue];
}
if (zot(alpha)) alpha == 1;
if (answer = color.match(/rgb\((.*)\)/)) {
if (toColorType == "rgba") {
var c = color.split(")");
return c[0]+","+alpha+c[1];
} else if (toColorType == "hex") {
var colors = getRGB(answer[1]);
return "#" + colors[0] + colors[1] + colors[2];
} else if (toColorType == "hexNumber") {
var colors = getRGB(answer[1]);
return parseInt(colors[0]+colors[1]+colors[2], 16);
} else if (toColorType == "string") {
var color = getRGB(answer[1]).join("").toLowerCase();
var index = hex.indexOf(color);
if (index == -1) return "#" + color;
else return colors[index];
} else return color;
}
if (toColorType == "rgb" || toColorType == "rgba") {
function hexToRgbA(hex){ // kennebec on StackOverflow
var c;
if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)){
c= hex.substring(1).split('');
if(c.length== 3){
c= [c[0], c[0], c[1], c[1], c[2], c[2]];
}
c= '0x'+c.join('');
if (toColorType == "rgb") {
return 'rgb('+[(c>>16)&255, (c>>8)&255, c&255]+')';
} else {
return 'rgba('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+','+alpha+')';
}
} else {
if (toColorType == "rgb") {
return "rgb(0,0,0)";
} else {
return "rgba(0,0,0,1)";
}
}
}
if (color.charAt(0)=="#") {
return hexToRgbA(color);
} else {
return hexToRgbA(zim.convertColor(color));
}
} else if (toColorType == "hex") {
if (color.charAt(0)=="#") return color; // already hex
} else if (toColorType == "hexNumber") {
if (color.charAt(0)=="#") {
return parseInt(color.replace(/^#/, ''), 16);
}
} else {
if (color.charAt(0)=="#") {
color = color.replace("#","");
if (color.length == 3) {
color = color.charAt(0)+color.charAt(0)+color.charAt(1)+color.charAt(1)+color.charAt(2)+color.charAt(2);
}
}
}
if (toColorType == "string") {
var index = hex.indexOf(color);
if (index == -1) return "#" + color;
else return colors[index];
} else if (toColorType == "hexNumber") {
return parseInt(hex[colors.indexOf(color.toLowerCase())!=-1?colors.indexOf(color):0], 16);
} else {
return "#"+hex[colors.indexOf(color.toLowerCase())!=-1?colors.indexOf(color):0];
}
};//-27.5
/*--
zim.colorRange = function(color1, color2, ratio)
colorRange
zim function
DESCRIPTION
Gets the color in a range between two colors based on a ratio from 0-1
Used internally by setColorRange() method and colorRange property of ZIM shapes
including animating color from current color to a new color
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
zog(colorRange(green, blue, .5)); // #7ecb7c
var rect = new Rectangle(100,100,red).center().setColorRange(purple);
rect.colorRange = .1; // will change color to #f1455e (closer to red than purple)
rect.animate({color:purple}, 1000); // will animate color to purple in one second
rect.wiggle("colorRange", .5, .2, .5, 1, 5); // wiggles the color in the range
END EXAMPLE
PARAMETERS
color1 - (default null) the first color as an HTML string or hex color (case insensitive)
color2 - (default black) the second color as an HTML string or hex color (case insensitive)
ratio - (default .5) the ratio where 0 is the first color and 1 the second color
RETURNS a hex color string
--*///+27.6
zim.colorRange = function(color1, color2, ratio) {
if (!zim.colorRangeCheck) {z_d("27.6"); zim.colorRangeCheck=true;}
// thanks Chris Dolphin - StackOverflow
// modified by Dan Zen to use hex input and output
// possibly converting and converting back - but not quite...
if (zot(ratio)) ratio = .5;
ratio = Math.max(0, Math.min(1, ratio));
if (zot(color1)) color1 = "white";
if (zot(color2)) color2 = "black";
var c1 = zim.convertColor(color1, "rgb");
var c2 = zim.convertColor(color2, "rgb");
var color1 = c1.substring(4, c1.length - 1).split(',');
var color2 = c2.substring(4, c2.length - 1).split(',');
var difference;
var newColor = "#";
var c;
for (var i=0; i= 0) return zim.colorRange(String(color), "#FFFFFF", ratio);
else return zim.colorRange(String(color), "#000000", -ratio);
};//-27.65
/*--
zim.darken = function(color, ratio)
darken
zim function
DESCRIPTION
Darkens the color by a ratio from 0 to 1
A shortcut for ZIM colorRange(color, black, ratio);
A shortcut method is also added to the JavaScript String
for instance:
red.darken(.2); // darkens ZIM red color
"red".darken(.2); // darkens HTML red color
"#cc0000".darken(.2); // darkens HTML Hex color
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// make a slightly darker than ZIM blue circle
new Circle(100, darken(blue, .2)).center();
// or use the String method directly
new Circle(100, blue.darken(.2)).center();
END EXAMPLE
PARAMETERS
color - the color as an HTML string or hex color (case insensitive)
can be ZIM colors as they are just references to hex colors
not used with color String method
ratio - (default .5) the ratio where 0 is the color and 1 black
RETURNS a hex color string
--*///+27.66
zim.darken = function(color, ratio) {
if (zot(ratio)) ratio = .5;
if (!zim.darkenCheck) {z_d("27.66"); zim.darkenCheck=true;}
if (ratio >= 0) return zim.colorRange(String(color), "#000000", ratio);
else return zim.colorRange(String(color), "#ffffff", -ratio);
};//-27.66
/*--
zim.toColor = function(color, targetColor, ratio)
toColor
zim function
DESCRIPTION
toColor the color by a ratio from 0 to 1
A shortcut for ZIM colorRange(color, white, ratio);
A shortcut method is also added to the JavaScript String
for instance:
red.toColor(blue, .2); // moves ZIM red color towards ZIM blue color
"red".toColor("blue", .2); // moves HTML red color towards HTML blue color
"#cc0000".toColor("#0000cc", .2); // moves HTML Hex red color towards HTML Hex blue color
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// make a ZIM blue circle be partway to ZIM pink
new Circle(100, toColor(blue, pink, .2)).center();
// or use the String method directly
new Circle(100, blue.toColor(pink, .2)).center();
END EXAMPLE
PARAMETERS
color - the color as an HTML string or hex color (case insensitive)
can be ZIM colors as they are just references to hex colors
not used with toColor String method
targetColor - the target color as an HTML string or hex color (case insensitive)
can be ZIM colors as they are just references to hex colors
ratio - (default .5) the ratio where 0 is the color and 1 targetColor
RETURNS a hex color string
--*///+27.67
zim.toColor = function(color, targetColor, ratio) {
if (!zim.toColorCheck) {z_d("27.67"); zim.toColorCheck=true;}
if (zot(ratio)) ratio = .5;
return zim.colorRange(String(color), targetColor, ratio);
};//-27.67
/*--
zim.toAlpha = function(color, alpha)
toAlpha
zim function
DESCRIPTION
Set the alpha of a the color by a ratio from 0 to 1
A shortcut for ZIM convertColor(color, "rgba", ratio);
A shortcut method is also added to the JavaScript String
for instance:
red.toAlpha(.2); // sets ZIM red color to .2 alpha
"red".toAlpha(.2); // sets HTML red color to .2 alpha
"#cc0000".toAlpha(.2); // sets HTML Hex red color to .2 alpha
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// make a ZIM blue circle be partway to ZIM pink
new Label({text:"HELLO", backgroundColor:blue.toAlpha(.5)}).pos(0,50,CENTER,BOTTOM);
END EXAMPLE
PARAMETERS
color - the color as an HTML string or hex color (case insensitive)
can be ZIM colors as they are just references to hex colors
not used with toAlpha String method
ratio - (default .5) the ratio where 0 is the color and 1 targetColor
RETURNS a hex color string
--*///+27.68
zim.toAlpha = function(color, ratio) {
if (!zim.toAlphaCheck) {z_d("27.68"); zim.toAlphaCheck=true;}
if (zot(ratio)) ratio = .5;
return zim.convertColor(String(color), "rgba", ratio);
};//-27.68
/*--
zim.zimEase = function(points, polynomials, convert)
zimEase
zim function
DESCRIPTION
Easing is used in animation usually to slow down or speed up as the animation starts or ends.
ZIM animate() has built in eases that handle the common types of easing - so look there first!
https://zimjs.com/docs.html?item=animate under the ease parameter.
The zimEase() function provides for custom easing beyond the built in eases and
returns an easing function to pass in to ZIM animate() - or CreateJS TweenJS
The points to pass in to zimEase() can be created at https://zimjs.com/ease
At the top of the app there are default easing functions
but just use the built in easing function for most of these such as "quadOut", etc.
SEE: https://zimjs.com/ease for the zimEase tool
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// go to https://zimjs.com/ease use the sliders and TEST the motion
// then press SAVE and copy the zimEase() code into ZIM animate()
// this example makes very big forward, back, forward motion
new Circle().loc(200,200).animate({
props:{x:400},
ease:zimEase([2.5,-0.5,-1,1]),
time:1.5
});
END EXAMPLE
EXAMPLE
// passing an array of two arrays will play the first for the first half
// and the second for the second half
// so here we pass an array of two arrays for a snapInOut effect
// this is cool so it is now a set of eases: "snapIn", "snapOut", "snapInOut" - cheers GreenSock!
new Circle().loc(200,200).animate({
props:{x:400},
ease:zimEase([[1.45,-0.57,0.67,0.55], [0.34,0.44,1.43,-0.31]]),
// ease:"snapInOut", // or use the new ZIM ease
time:2
});
END EXAMPLE
PARAMETERS
points - (default [.2,.4,.6,.8]) an array of 4 points to feed the equation - or an array of two arrays
use the tool at https://zimjs.com/ease and press SAVE to get these
the two ends are anchored at 0 and 1 and are the input to the quintic Bezier formula
If an array of two arrays is provided the first array is used for the first half of the tween (In)
and the second array is used for the second half of the tween (Out)
polynomials - (default null) an array of 5 points that are the results of the quintic Bezier formula
linear would be [0,0,0,0,1] - use this if you are given the polynomials - who knows!
otherwise see points.
mirror - (default null) will duplicate the ease equation and reverse the second copy all within the provided time
reverse - (default false) reverses the ease equation (does not work with mirror)
lockEnds - (default true) this snaps the start and end to the real values - set to false to draw curve based on data, for instance.
PROPERTIES
** The function result is an object that holds the easing equation in a noPick property
** this allows it to bypass the dynamic setting of ZIM VEE ease parameter.
** Also in this object are the additional properties
points - the array of points or the array of arrays of points
polynomials - the array of final values or an array of arrays of final values
RETURNS an easing function for ZIM animate() or CreateJS TweenJS
--*///+27.69
zim.zimEase = function(points, polynomials, mirror, reverse, lockEnds) {
z_d("27.69");
// with thanks to Timothée Groleau and all before
// http://www.timotheegroleau.com/Flash/experiments/easing_function_generator.htm
var two = false;
if (zot(lockEnds)) lockEnds=true;
if (points) {
if (Array.isArray(points[1])) {
two = true;
points2 = points[1];
points = points[0];
var c0z = 0;
var c1z = points2[0];
var c2z = points2[1];
var c3z = points2[2];
var c4z = points2[3];
var c5z = 1;
var ez = 5*(c1z - c0z);
var dz = 10*(c2z - c0z) - 4*ez;
var cz = 10*(c3z - c0z) + 30*(c1z - c2z);
var bz = 5*(c4z + c0z) - 20*(c3z + c1z) + 30*c2z;
var az = c5z - c0z - bz - cz - dz - ez;
}
var c0 = 0;
var c1 = points[0];
var c2 = points[1];
var c3 = points[2];
var c4 = points[3];
var c5 = 1;
var e = 5*(c1 - c0);
var d = 10*(c2 - c0) - 4*e;
var c = 10*(c3 - c0) + 30*(c1 - c2);
var b = 5*(c4 + c0) - 20*(c3 + c1) + 30*c2;
var a = c5 - c0 - b - c - d - e;
} else if (polynomials) {
var a = polynomials[0];
var b = polynomials[1];
var c = polynomials[2];
var d = polynomials[3];
var e = polynomials[4];
// calculate points - for consistent points property
var c1 = e / 5;
var c2 = (d+4*e)/10;
var c3 = (c + 6*e + 3*d)/10;
var c4 = (b + 4*e + 3*d + 2*c)/5;
} else {
var a = 0;
var b = 0;
var c = 0;
var d = 0;
var e = 1;
}
// return CreateJS ratio format with variables in enclosure
// looks like a lot of code but the tween code is just the function in noPick
// so we are putting the conditionals outside this during the single assignment
// this keeps the tween function fast as that runs at the framerate
if (mirror) {
var rF = function(){
return zim.zimEase(null,[a,b,c,d,e],true) // mirror would be the same
};
var obj = {
reverse:rF,
points:[c1,c2,c3,c4],
polynomials:[a,b,c,d,e]
}
obj.noPick = function(k) {
if (lockEnds) {
if (k<.025) return 0;
if (k>.975) return 1;
}
if (k<.5) {
k*=2; // k needs to be 0-1 to get full tween
var t = k*100;
var di = 100;
var ts=(t/=di)*t;
var tc=ts*t;
// the completeness is divided by 2
return (a*tc*ts + b*ts*ts + c*tc + d*ts + e*t)/2;
} else {
k=1-(k-.5)*2; // we use the second half of k but spread it out from 0 to 1 for complete formula (reversed for mirror)
var t = k*100;
var di = 100;
var ts=(t/=di)*t;
var tc=ts*t;
// the completeness is added to the second half and still divided by 2 (1 - for mirror)
return 1-(a*tc*ts + b*ts*ts + c*tc + d*ts + e*t)/2;
}
}
} else if (two) {
var rF = function(){
if (zon) zogy("zimEase - multi array points cannot be reversed");
return zim.zimEase(null,[a,b,c,d,e])
};
var obj = {
reverse:rF,
points:[[c1,c2,c3,c4],[c1z,c2z,c3z,c4z]],
polynomials:[[a,b,c,d,e],[az,bz,cz,dz,ez]]
}
obj.noPick = function(k) {
if (lockEnds) {
if (k<.025) return 0;
if (k>.975) return 1;
}
if (k<.5) {
k*=2; // k needs to be 0-1 to get full tween
var t = k*100;
var di = 100;
var ts=(t/=di)*t;
var tc=ts*t;
// the completeness is divided by 2
return (a*tc*ts + b*ts*ts + c*tc + d*ts + e*t)/2;
} else {
k=(k-.5)*2; // we use the second half of k but spread it out from 0 to 1 for complete formula
var t = k*100;
var di = 100;
var ts=(t/=di)*t;
var tc=ts*t;
// the completeness is added to the second half and still divided by 2
return .5+(az*tc*ts + bz*ts*ts + cz*tc + dz*ts + ez*t)/2;
}
}
} else {
var rF = function(){
return zim.zimEase(null,[a,b,c,d,e],null,true)
};
var obj = {
reverse:rF,
points:[c1,c2,c3,c4],
polynomials:[a,b,c,d,e]
}
if (reverse) {
obj.noPick = function(k) {
if (lockEnds) {
if (k<.025) return 0;
if (k>.975) return 1;
}
var t = 100-k*100; // reverse the time
var di = 100;
var ts=(t/=di)*t;
var tc=ts*t;
return 1-(a*tc*ts + b*ts*ts + c*tc + d*ts + e*t); // reverse the percent done
}
} else {
obj.noPick = function(k) {
if (lockEnds) {
if (k<.025) return 0;
if (k>.975) return 1;
}
var t = k*100;
var di = 100;
var ts=(t/=di)*t;
var tc=ts*t;
return (a*tc*ts + b*ts*ts + c*tc + d*ts + e*t);
}
}
}
obj.noPick.reverse = rF; // for once it is picked...
return obj;
}//-27.69
/*--
zim.pointAlongCurve = function(points, ratio, getAngle)
pointAlongCurve
zim function
DESCRIPTION
Finds a point along a cubic Bezier curve - such as that used in Blob and Squiggle
as well as the Shape.graphics.bezierCurveTo() or tiny api bt()
Used internally for animating along Blob and Bezier curves
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// point1, control1, control2, point2
var points = [{x:100,y:100}, {x:200,y:100}, {x:200,y:100}, {x:200,y:200}]
var shape = new Shape().addTo();
shape.graphics
.s("black").ss(2)
.mt(points[0].x,points[0].y)
.bt(points[1].x,points[1].y, points[2].x,points[2].y, points[3].x,points[3].y);
new Circle(10,red).loc(pointAlongCurve(points, .2));
END EXAMPLE
PARAMETERS
points - an array of point objects (or objects with an x and y property)
for a cubic Bezier - point1, control1, control2, point2
ratio - (default .5) the ratio where 0 is at the first point and 1 is at the second point
getAngle - (default false) request a calculated angle of tangent at point
even - (default false) use modified cubic equation for even spacing for percentages
even is used by Beads but not by placing a point along a path
RETURNS a point object with x and y properties on the curve at the ratio
as well as an angle property for the tangent if getAngle is true
--*///+27.7
zim.pointAlongCurve = function(points, ratio, getAngle, even) {
z_d("27.7");
if (!points || !points[0] || !points[1] || !points[2] || !points[3]) return;
if (zot(even)) even = false;
var cubic = new zim.Bezier(points[0],points[1],points[2],points[3]);
if (even) {
var x=cubic.mx(ratio);
var y=cubic.my(ratio);
} else {
var x=cubic.x(ratio);
var y=cubic.y(ratio);
}
if (getAngle) {
var lastRatio = ratio-.05;
var nextRatio = ratio+.05;
if (lastRatio < 0) lastRatio = 0;
if (nextRatio > 1) nextRatio = 1;
if (even) {
var x0=cubic.mx(lastRatio);
var y0=cubic.my(lastRatio);
var x2=cubic.mx(nextRatio);
var y2=cubic.my(nextRatio);
} else {
var x0=cubic.x(lastRatio);
var y0=cubic.y(lastRatio);
var x2=cubic.x(nextRatio);
var y2=cubic.y(nextRatio);
}
var angle = zim.angle(x0, y0, x2, y2);
return({x:x,y:y,angle:angle});
}
return({x:x,y:y});
};//-27.7
/*--
zim.distanceAlongCurve = function(points)
distanceAlongCurve
zim function
DESCRIPTION
Finds approximate distance along a cubic Bezier curve - such as that used in Blob and Squiggle
as well as the Shape.graphics.bezierCurveTo() or tiny api bt()
Used internally for animating along Blob and Bezier curves
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// point1, control1, control2, point2
var points = [{x:100,y:100}, {x:200,y:100}, {x:200,y:100}, {x:200,y:200}]
var shape = new Shape();
shape.graphics
.s("black").ss(2)
.mt(points[0].x,points[0].y)
.bt(points[1].x,points[1].y, points[2].x,points[2].y, points[3].x,points[3].y);
zog(distanceAlongCurve(points)); // 170.7
END EXAMPLE
PARAMETERS
points - an array of point objects (or objects with an x and y property)
for a cubic Bezier - point1, control1, control2, point2
RETURNS an approximate distance along the curve
--*///+27.8
zim.distanceAlongCurve = function(points) {
z_d("27.8");
// Thanks David F. Knight in OpenGl.org forumn
// points are [startPt, controlPt1, controlPt2, endPt]
var chord = zim.dist(points[0], points[3]);
var controlDist = zim.dist(points[0], points[1]) + zim.dist(points[1], points[2]) + zim.dist(points[2], points[3]);
return (chord + controlDist)/2;
};//-27.8
/*--
zim.closestPointAlongCurve = function(point, segmentPoints, num, interpolate, percentage)
closestPointAlongCurve
zim function
DESCRIPTION
Finds the closest point along a cubic Bezier curve before the given point.
Blob and Squiggle use cubic Bezier as does the Shape.graphics.bezierCurveTo() or tiny api bt()
Used internally for adding points to a Blob and Bezier curves
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var blob = new Blob().center();
var points = blob.segmentPoints;
stage.on("stagemousedown", function (e) {
var point = blob.globalToLocal(e.stageX, e.stageY)
zog(closestPointAlongCurve({x:point.x, y:point.y}, points))
// gives index of point on curve before mouse location
});
END EXAMPLE
PARAMETERS
point - an object with an x and y property
this could be {x:100, y:140} or circle, etc.
the results tell which segment to add the point to
the segment starting with the returned index
segmentPoints - an array of cubic Bezier point data
each being an array of points for a cubic Bezier
in the format of [point1, control1, control2, point2]
Note, this is not the same as Blob or Squiggle points
but rather use the segmentPoints property of Blob and Squiggle
num - (default 10) the number of points per segment used to calculate answer
interpolate - (default false) will return closest test point - not index of closest existing point
percentage - (default false) will return percent (0-100) the nearest point is on the path (overrides interpolate)
RETURNS the index of the closest point in segmentPoints before the given point
or if interpolate is true, will return the closest testPoint (use higher num for better result)
or if percentage is true, will return percent (0-100) the nearest point is on the path (overrides interpolate)
--*///+27.9
zim.closestPointAlongCurve = function(point, segmentPoints, num, interpolate, percentage) {
z_d("27.9");
var closest = 10000000;
var closestTestPoint;
var index = 0;
var secondaryIndex = 0;
if (zot(num)) num = 10;
zim.loop(segmentPoints, function(points, i, t) {
// add num more points to estimate closest
var cubic = new zim.Bezier(points[0],points[1],points[2],points[3]);
zim.loop(num, function (j, total) {
// var d = zim.dist(point, zim.pointAlongCurve(segmentPoints(that.points[i], that.points[i .5)) {
if (c.toUpperCase) c = c.toUpperCase();
} else {
if (c.toLowerCase) c = c.toLowerCase();
}
id += String(c);
}
return id;
};//-13.5
/*--
zim.swapProperties = function(property, objA, objB)
swapProperties
zim function
DESCRIPTION
Pass in a property as a string and two object references
and this function will swap the property values.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// exchanges the x position of two ZIM circles
swapProperties("x", circle1, circle2); stage.update();
END EXAMPLE
PARAMETERS
property - a String of the property to swap values eg. "alpha"
objA, objB - the objects on which to swap properties
RETURNS Boolean indicating success
--*///+17.1
zim.swapProperties = function(property, objA, objB) {
z_d("17.1");
if (zot(objA) || zot(objB) || zot(objA[property]) || zot(objB[property])) return false;
var temp = objB[property];
objB[property] = objA[property];
objA[property] = temp;
return true;
};//-17.1
/*--
zim.mobile = function(orientation)
mobile
zim function
DESCRIPTION
Detects if app is on a mobile device - if so, returns the mobile device type:
android, ios, blackberry, windows, other (all which evaluate to true) else returns false.
orientation defaults to true and if there is window.orientation then it assumes mobile
BUT this may return true for some desktop and laptop touch screens
so you can turn the orientation check off by setting orientation to false.
If orientation is set to false the check may miss non-mainstream devices
The check looks at the navigator.userAgent for the following regular expression:
/ip(hone|od|ad)|android|blackberry|nokia|opera mini|mobile|phone|nexus|webos/i
Microsoft mobile gets detected by nokia, mobile or phone.
NOTE: See also the ZIM MOBILE constant - this can be set to true or false to override mobile()
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
if (mobile()) {
var pane = new Pane(300, 200, "Desktop Only");
pane.show();
}
END EXAMPLE
PARAMETERS
orientation - (default true) uses window.orientation property to determine mobile
this may call certain touch screens mobile
but setting to false uses a test on mobile names which could be incomplete
RETURNS a String or false
--*///+28
zim.mobile = function(orientation) {
z_d("28");
if (typeof MOBILE != "undefined" && MOBILE!="default") return MOBILE;
if (!zot(zim.MOBILE) && zim.MOBILE!="default") return zim.MOBILE;
if (zot(orientation)) orientation = true;
if (/ip(hone|od|ad)/i.test(navigator.userAgent)) return "ios";
if (/android|nexus/i.test(navigator.userAgent)) return "android";
if (/blackberry/i.test(navigator.userAgent)) return "blackberry";
if (/nokia|phone|mobile/i.test(navigator.userAgent)) return "windows";
if (/opera mini|webos/i.test(navigator.userAgent)) return "other";
if (orientation && window.orientation !== undefined) {
if (/safari/i.test(navigator.userAgent)) return "ios";
return true;
}
return false;
};//-28
//
/*--
zim.vee = function(obj)
vee
zim function
DESCRIPTION
Determines if obj is a ZIM Pick() object or a Pick Literal - used by ZIM VEE parameters
Pick Literal format is [], {min:a, max:b}, function(){}, {noPick:x} or a function(){}
See https://zimjs.com/docs.html?type=Pick
ZIM Pick is a way to pass in dynamic parameters or style properties
This is very handy to pass in a series() function or an array for random pickings, etc.
Used to create dynamic particles with the Emitter or tile specific items in order, etc.
Pick.choose() accepts any value and if not in ZIM Pick format, will just return the object
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var color = [red, green, blue];
// ternary operator - if in Pick format, add "random" else ""
new Label((vee(color)?"random ":"") + "colors").center();
END EXAMPLE
PARAMETERS
obj - an object to pass in to test whether it is in ZIM VEE (Pick) format
RETURNS a Boolean true if Pick format or false if not (such as just a number, string, new Circle, etc.)
--*///+28.5
zim.vee = function(obj) {
z_d("28.5");
return !zot(obj) && (obj.type == "Pick" || Array.isArray(obj) || (obj.constructor == {}.constructor && (!zot(obj.max) || !zot(obj.noPick))) || typeof obj == "function");
};//-28.5
/*--
zim.extend = function(subclass, superclass, override, prefix, prototype)
extend
zim function - modified CreateJS extend and promote utility methods
DESCRIPTION
For ES5 - place after a sub class to extend a super class.
Extending a super class means that the sub class receives all the properties and methods of the super class.
For example, a ZIM Container() extends a CreateJS Container and then adds more methods and properties
but all the CreateJS Container methods and properties are still there too like x, y, addChild(), etc.
For ES6 - do not use zim.extend() but rather use the built in ES6 structures as follows:
EXAMPLE
// ES6 - do NOT use zim.extend()
class Person() {
constructor () {
zog("I am a person");
}
}
class Woman extends Person { // use JS6 extends keyword
constructor () {
super(); // use JS6 super() to call the Person constructor - will do the zog()
// Woman code
}
}
// ES6 to extend a zim Container for example (do NOT use zim.extend() in ES6)
class ChineseCoin extends Container { // use JS6 extends keyword
constructor () {
super(); // must call the zim Container before using keyword this
new Circle(100, "gold").addTo(this); // this will be the zim Container
new Rectangle(100, 100, "brown").center(this);
}
}
var coin = new ChineseCoin().center(); // coin is a zim Container with Circle and Rectangle inside
END EXAMPLE
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// ES5 examples using functions to make classes
// ES5 has no extends keyword and no super keyword so we use zim.extends()
function Person() {
this.talk = function() {
zog("I am a person");
}
}
function Woman() {
this.super_constructor(); // part of the zim.extend() system
}
extend(Woman, Person); // here is the zim.extend() for ES5
var woman = new Woman();
woman.talk();
END EXAMPLE
NOTE: CreateJS display objects require their constructor to be called otherwise it is like quantum entanglement (seriously)
extend() adds access to the super class constructor so it can be called in the subclass as follows:
this.super_constructor();
It also provides access to super class methods that are overridden
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// ES5 example - see the ES6 set of examples for ES6 ;-)
// make a Collection class that will extend a Container
// the Collection class will call the Container constructor
// and override the the ZIM Container center method in the class body
// and override the CreateJS Container addChild method in the prototype
// either method would work in either place - it is often a matter of preference
// but you might need to use a method in the class body to access local variables
// The ZIM extend() method parameter values need to change depending on where you override
// see the comments inline for the instructions
var Collection = function() {
// for CreateJS the super constructor must be run
this.super_constructor();
// override the zim center() method
// methods in the function call that override must be passed in as an array of strings
// to the override parameter of extend() to be able to access the super_method
this.center = function(where) {
this.super_center(where);
this.y -= 50;
}
}
// override the super class addChild() that comes from the CreateJS Container
// methods on the prototype that override are automatically provided a super_method
// unless the prototype parameter of extend() is set to false (default is true)
Collection.prototype.addChild = function(c) {
this.super_addChild(c); // call the super class addChild
zog("added a child to Collection");
}
// make the Collection extend a Container()
// it will receive all the properties and methods of the Container plus its own
extend(Collection, Container, "center"); // or pass an array of overridden methods
// use the Collection
var c = new Collection();
c.addChild(new Rectangle(100, 100, green)); // zogs "added a child to Collection"
c.center(); // centers the collection but then offsets it 50 pixels up
END EXAMPLE
NOTE: the superclass constructor is always available as this.prefix_constructor() no matter the override or prototype settings
NOTE: this.prefix_constructor(); should be called at the top of the subclass to avoid problems when multiple copies of object
NOTE: to extend a class that already extends a ZIM class then change the prefix to a unique name:
EXAMPLE
// if we already had the Collection example above and we want to extend that
// then we must use a new prefix when using extend()
var Records = function() {
this.Collection_constructor();
}
extend(Records, Collection, null, "Collection");
// you will still have this.super_center(), this.super_addChild() if needed
// plus any newly overridden methods available as this.Collection_methodName() etc.
var r = new Records();
r.addChild(new Circle(20, pink));
r.super_center(); // call the original center (without vertical shift)
// to extend again, use yet another prefix - for example: "Records"
var Jazz = function() {
this.Records_constructor();
}
extend(Jazz, Records, null, "Records");
END EXAMPLE
PARAMETERS supports DUO - parameters or single object with properties below
NOTE: do NOT use zim.extend() with ES6 - see ES6 examples at top instead
subclass - the class to extend
superclass - the class to extend from (an existing class)
override - (default null) an Array of methods (as Strings) to override.
You can override any function by just defining that function in the subclass
the override parameter gives you access to the overridden function in the superclass prototype
only methods on the superclass prototype can be accessed once overridden - not methods in the superclass body
if there is only one method being overridden then a single string is fine ("test" or ["test"] is fine)
any methods passed to this parameter will be given prefix_methodName() access on the sub class (this.prefix_methodName())
where the prefix is below (note, the prototype setting has no bearing on these manual overrides)
this list is only needed for methods in the subclass body
methods assigned to the prototype of the subclass that override are automatically given prefixes
prefix - (default "super") a prefix that will be followed by "_" and then the overridden method name
by default this.super_constructor() would call the super class constructor
if prefix is set to "Person" then this.Person_constructor() would call the super class constructor
the same system is used to call overridden files in override or prototype
prototype - (default true) will search the subclass prototype for overriding methods
the overridden methods are then available as this.prefix_methodName()
set to false to avoid searching the super class for methods overridden by the sub class prototype
just quickens the code minutely if there is no need
NOTE: extend() is included in Distill if DISPLAY, METHODS or FRAME Module classes are used (otherwise NOT included)
RETURNS the subclass
--*///+50.35
zim.extend = function(subclass, superclass, override, prefix, prototype) {
var sig = "subclass, superclass, override, prefix, prototype";
var duo; if (duo = zob(zim.extend, arguments, sig)) return duo;
if (zot(subclass) || zot(superclass)) {
if (zon && subclass!=zim.StageGL) zog("zim.extend() - please supply a class and its superclass");
return;
}
// zogr("start")
if (zot(prefix)) prefix = "super";
if (zot(override)) override = [];
if (!Array.isArray(override)) override = [override];
if (zot(prototype)) prototype = true;
// modified CreateJS extend() to include any prototype members already added
// see http://www.createjs.com/docs/easeljs/classes/Utility%20Methods.html
var existingP = {};
for (var f in subclass.prototype) Object.defineProperty(existingP,f,Object.getOwnPropertyDescriptor(subclass.prototype, f));
function o() {this.constructor = subclass;}
o.prototype = superclass.prototype;
subclass.prototype = new o();
for (f in existingP) {
Object.defineProperty(subclass.prototype,f,Object.getOwnPropertyDescriptor(existingP,f));
}
// modified CreateJS promote() to promote methods other than constructor only if methods is true
// zim does not override with prototypes so it is uneccessary to loop through the super class methods
// added checking an array of string values of methods defined in class (not prototype) that are being overridden
var subP = subclass.prototype;
var supP = (Object.getPrototypeOf&&Object.getPrototypeOf(subP))||subP.__proto__;
if (supP) {
subP[(prefix+="_") + "constructor"] = supP.constructor; // constructor is not always innumerable
var n;
for (var i=0; i 0 && answer != 0) {
// var place = String(answer).indexOf(".");
// var length = String(answer).length;
// if (place < 0) {place = length++; answer+=".";}
// for (var i=0; i 0) {
var place = String(answer).indexOf(".");
var length = String(answer).length;
if (place < 0) {place = length++; answer+=".";}
for (var i=0; i 1) {
// fix this - Dan Zen - negative decimal number problem
if (sign == -1) answer = answer.substr(1,answer.length-1);
var place = String(answer).indexOf(".");
var length = String(answer).length;
var left = (place < 0) ? length : place;
for (var i=0; i 0) && !includeZero && Number(answer) == 0) answer = 0;
if (time) answer = String(answer).replace(".", ":");
return zim.zut(evt) ? answer : null;
};//-13
/*--
zim.countDecimals = function(num)
countDecimals
zim function
DESCRIPTION
Counts the number of decimals in a number
Provided by Matthew Layton, A. Wolff - Stack Overflow
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var num1 = countDecimals(1.234); // num1 is 3
var num2 = countDecimals(22); // num2 is 0
END EXAMPLE
PARAMETERS
num - the Number for which to count decimals
RETURNS the number of decimal places
--*///+13.05
zim.countDecimals = function(num) {
if (!zim.zimCountDecimalsCheck) {z_d("13.05"); zim.zimCountDecimalsCheck = true;}
return num % 1?num.toString().split(".")[1].length:0;
};//-13.05
/*--
zim.sign = function(num)
sign
zim function
DESCRIPTION
returns -1, 0 or 1 depending on whether the number is less than, equal to or greater than 0
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var speed = 20;
zog(sign(speed)); // 1
var speed = 0;
zog(sign(speed)); // 0
var speed = -20;
zog(sSign(speed)); // -1
END EXAMPLE
PARAMETERS
num - the Number to operate on
RETURNS -1, 0 or 1
--*///+13.1
zim.sign = function(num) {
if (!zim.zimSignCheck) {z_d("13.1"); zim.zimSignCheck=true;}
return num?num<0?-1:1:0;
};//-13.1
/*--
zim.constrain = function(num, min, max, negative)
constrain
zim function
DESCRIPTION
returns a number constrained to min and max
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var cirle.x = constrain(circle.x, circle.radius, stageW-circle.radius);
// circle.x will not be smaller than the radius or bigger than stageW-radius
var speed = constrain(speed, minSpeed, maxSpeed, true);
// will confine the speed between minSpeed and maxSpeed if speed is positive
// and confine the speed between -maxSpeed and -minSpeed if the speed is negative
END EXAMPLE
PARAMETERS
num - the number to be constrained
min - (default 0) the minimum value of the return number
max - (default Number.MAX_VALUE) the maximum value of the return number
negative - (default false) allow the negative range of min and max when num is negative
RETURNS num if between min and max otherwise returns min if less or max if greater (inclusive)
RETURNS num between -max and -min if num is negative and negative parameter is set to true
--*///+13.2
zim.constrain = function(num, min, max, negative) {
z_d("13.2");
if (zot(num)) return;
if (zot(min)) min = 0;
if (zot(max)) max = Number.MAX_VALUE;
if (max < min) {var max2 = min; max = min; min = max2;} // ES6 Fix to come
if (zot(negative)) negative = false;
if (negative && num < 0) {
return Math.max(-max, Math.min(num, -min));
} else {
return Math.max(min, Math.min(num, max));
}
};//-13.2
/*--
zim.dist = function(a, b, c, d)
dist
zim function
DESCRIPTION
Calculates the distance between two points.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// using point values for each
var p1 = new Point(100, 100); // or {x:100, y:100}
var p2 = new Point(200, 200);
zog(dist(p1, p2)); // 141.42...
END EXAMPLE
EXAMPLE
// using x and y values for each
var distance = dist(stageW/2, stageH/2, frame.mouseX, frame.mouseY);
// distance of mouse from center of stage
END EXAMPLE
PARAMETERS
a - first Point - any object with x and y values - eg. a zim Container or zim Point or {x:10, y:30}
or if four parameter values, an x value of the first point
b - second Point - any object with x and y values
or if four parameter values, a y value of the first point
c - (default null) an x value of a second point - if using x and y values
d - (default null) a y value of a second point - if using x and y values
RETURNS a positive Number that is the distance (could be on an angle)
--*///+13.3
zim.dist = function(a, b, c, d) {
if (!zim.zimDistCheck) {z_d("13.3"); zim.zimDistCheck=true;}
if (zot(a) || zot(b)) return;
if (!zot(a.x) && !zot(b.x)) {
d = b.y;
c = b.x;
b = a.y;
a = a.x;
} else {
if (zot(c)) c = 0;
if (zot(d)) d = 0;
}
return Math.sqrt((Math.pow(c-a, 2) + Math.pow(d-b, 2)));
};//-13.3
/*--
zim.rectIntersect = function(a, b, margin)
rectIntersect
zim function
DESCRIPTION
Returns true if two rectangles are intersecting - this is a very fast but exact calculation
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// using point values for each
var r1 = {x:100, y:100, width:300, height:200}
var r2 = new Boundary(50,200,100,100);
zog(rectIntersect(r1, r2)); // true
END EXAMPLE
PARAMETERS
a - first rectangle with x, y, width and height properties - such as a bounds or Boundary
make sure that these are in the same coordinate systems - use ZIM boundsToGlobal for instance
b - second rectangle with x, y, width and height properties
margin - (default 0) positive value adds margin (more likely to intersect) and negative subtracts (less likely to intersect)
RETURNS a Boolean as to whether rectangles are intersecting
--*///+13.32
zim.rectIntersect = function(a, b, margin) {
if (!zim.zimRectIntersectCheck) {z_d("13.32"); zim.zimRectIntersectCheck=true;}
if (zot(margin)) margin = 0;
if (a.x >= b.x + b.width + margin || a.x + a.width + margin <= b.x ||
a.y >= b.y + b.height + margin || a.y + a.height + margin <= b.y ) {
return false;
} else {
return true;
}
};//-13.32
/*--
zim.boundsAroundPoints = function(points)
boundsAroundPoints
zim function
DESCRIPTION
Returns a rectangle {x,y,width,height} around an array of points {x,y}
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var blob = new Blob();
var points = blob.interpolate();
zog(boundsAroundPoints(points)); // {x:-100, y:-100, width:200, height:200}
// could call this after resizing the blob to get the rough bounds of the blob (or squiggle)
// interpolate defaults to 1 so setting 5 would be even more precise, etc.
END EXAMPLE
PARAMETERS
points - an array of points with x and y properties.
RETURNS an object with x, y, width and height properties
representing the rectangle around the points provided
--*///+13.34
zim.boundsAroundPoints = function(points) {
if (!zim.zimBoundsAroundPointsCheck) {z_d("13.34"); zim.zimBoundsAroundPointsCheck=true;}
var tX = 10000;
var tY = 10000;
var bX = -10000;
var bY = -10000;
for (var i=0; i bX) bX = p.x;
if (p.y < tY) tY = p.y;
if (p.y > bY) bY = p.y;
}
return {x:tX, y:tY, width:bX-tX, height:bY-tY};
};//-13.34
/*--
zim.angle = function(x1, y1, x2, y2)
angle
zim function
DESCRIPTION
Calculates the angle between two points relative to the positive x axis
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var angle = angle(stageW/2, stageH/2, stageW/2+100, stageH/2+100); // 45
// angle from center of stage to 100, 100 to the right and down from the center of the stage
var angle2 = angle(stageW/2, stageH/2, stageW/2-100, stageH/2+100); // 135
var angle3 = angle(stageW/2, stageH/2, stageW/2+100, stageH/2-100); // 315
END EXAMPLE
PARAMETERS
x1, y1 - first point x and y
unless no second point in which case x1, y1 will be second point and first point will be 0, 0
x2, y2 - second point x and y
RETURNS a positive Number that is the angle between first and second point relative to positive x axis
--*///+13.4
zim.angle = function(x1, y1, x2, y2) {
if (!zim.angleCheck) {z_d("13.4"); zim.angleCheck = true;}
if (zot(x1) || zot(y1)) return;
if (zot(x2)) {x2 = x1; x1 = 0;}
if (zot(y2)) {y2 = y1; y1 = 0;}
return (Math.atan2(y2-y1, x2-x1)*180/Math.PI+360)%360;
};//-13.4
/*--
TAU, DEG, RAD
TAU, DEG, RAD
zim constants
DESCRIPTION
ZIM degrees and radian constants
If working in radians, TAU is equal to 2 radians (360).
This allows easy visualization of angles - TAU/2 is 180, TAU/4 is 90, etc.
DEG is 180/Math.PI so you multiply a radian value by DEG to get degrees.
RAD is Math.PI/180 so you multiply a degree value by RAD to get radians.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
Math.sin(TAU/4); // sin of 90 degrees (1)
// is same as
Math.sin(90*RAD);
// is same as
Math.sin(90*Math.PI/180);
// and
Math.asin(1)*DEG; // is 90
END EXAMPLE
--*///+83.6
zim.TAU = Math.PI * 2;
zim.DEG = 180/Math.PI;
zim.RAD = Math.PI/180;
//-83.6
/*--
zim.smoothStep = function(num, min, max)
smoothStep
zim function
DESCRIPTION
smoothStep takes an input value and outputs a value between 0 and 1
that represents a transition between the min and max with easing at both ends.
If you want the easing to be more pronounced, then reduce difference between min and max.
If the value falls outside the min or max then it is set to the min or max.
Remember the return value is between 0 and 1 so you can multiply by max-min and add it to min
to get a value at the original scale.
Used to make blobs with Noise(): https://zimjs.com/noise/blobs.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// here we use smoothStep to make a gradient between black and white
// not an even one right across but a gradient across a transition zone of 40-100
// create an empty Bitmap size 200, 200 and center it on the stage
var bmp = new Bitmap(null, 200, 200).center();
// we need to loop and get a value for each pixel
// normally we loop across the rows and then do each column
// but here we are making a horizontal gradient
// so we will loop across the x and get the desired value
// then when we loop across the y in the inner loop, we just use that same value
for (var x = 0; x < bmp.width; x++) {
// making gradient in x only so calculate smoothStep here
// x will be from 0 to the width of 200
// we pass in a min of 40 and a max of 100
// the result of smoothStep is between 0 and 1
// so from 0 to 40 the return of smoothStep will be 0
// and from 100 to 200 the return of smoothStep will be 1
// In between, the return value starts off close to 0, then speeds up
// and then slows down to 1 in a curve that is somewhat like the letter f
// When we multiply by 255 and apply that result to each color,
// we get black and then a range of greys and then white
var value = smoothStep(x, 40, 100)*255;
// now we loop down the column for the x position
for (var y = 0; y < bmp.height; y++) {
// imageData is four values per pixel
// the red, green, blue and alpha
// in one big long array - each value will be constrained to between 0 and 255
// this i value will increase by 4 each time
// then we write the same value for red, green, blue to get a shade of grey
var i = (x + y * bmp.width) * 4;
bmp.imageData.data[i] = value; // red (0-255)
bmp.imageData.data[i + 1] = value; // green (0-255)
bmp.imageData.data[i + 2] = value; // blue (0-255)
bmp.imageData.data[i + 3] = 255; // alpha (0-255)
}
}
bmp.drawImageData(); // draw the imageData to the Bitmap
END EXAMPLE
PARAMETERS
num - the input value with respect to min and max
min - the lower edge for smoothStep (often termed edge0) - anything smaller will be set to min
max - the upper edge for smoothStep (often termed edge1) - anything bigger will be set to max
RETURNS a number between 0 and 1 that represents a transition factor
--*///+13.7
zim.smoothStep = function(num, min, max) {
z_d("13.7");
var x = zim.constrain((num - min)/(max - min), 0, 1);
return x*x*x*(x*(x*6 - 15) + 10); // Perlin
};//-13.7
// SUBSECTION CLASSES
/*--
zim.Ajax = function(master, couple, lock, unique)
Ajax
zim class
DESCRIPTION
An AJAX class to send data back and forth to a server without reloading the page
NOTE: also see ZIM async() to send data back and forth as JSONp
using async can avoid various security issues with cross domain access
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// GET - note: GET is limited to approximately 2048 characters
var ajax = new Ajax();
new Button().center().tap(function () {
ajax.get("https://yourserver/ajax.php?record=pressed");
});
END EXAMPLE
EXAMPLE
// GET with user input and server response
var query = new TextArea(300,90).center();
new Button({label:"SUBMIT", corner:5}).sca(.7).pos(0,100,CENTER,CENTER)
.tap(function () {
new Ajax().get("https://yourserver/ajax.php?query="+encodeURI(query.text), callback);
});
function callback(data) {
query.text = "Date: " + data.date + "\nAnswer: " + data.answer;
}
END EXAMPLE
EXAMPLE
// POST - virtually unlimited size
var ajax = new Ajax();
new Button().center().tap(function () {
var data = {name:"Dr Abstract", occupatio:"creator"};
// data will automatically have JSON.stringify() applied
var id = "AB234";
ajax.post("https://yourserver/ajax.php", data, "add", id, callback);
});
function callback(data) {
zog(data.name); // "Dr Abstract"
}
END EXAMPLE
EXAMPLE
// put - sends data in body of content
// same as POST but no command and receive in PHP as follows:
END EXAMPLE
PARAMETERS
master - data to be sent with every get() or post() (not put())
this can be collected in php, for example, as $GET_["master"] or $POST_["master"]
couple - (default false) - set to true to turn nested JSON into a single layer
** for POST only - use ZIM couple() and decouple() manually with GET and PUT
see ZIM couple() and decouple() for more information
data for POST will be coupled when sent and uncoupled when received
lock - (defualt null) send an optional lock id - would need to be processed on the server
unique - (defualt null) send an optional unique=true - would need to be processed on the server
METHODS
get(url, call) - send and receive based on GET (approximate limit 2048 characters)
the url will have parameters in cgi format to send information
for example: "server.php?name="+encodeURI("Dr Abstract")+"&occupation=creator";
in PHP access these with $_GET["name"], $_GET["occupation"], etc.
call is the function to call and will receive (data, error) as parameters
the data will automatically have JSON.parse() applied if in JSON format
post(url, data, command, extra, call) - send and receive based on POST
** accepts the ZIM DUO technique of regular parameters or a configuration object with properties matching parameters
url is the url to a server script such as php or node
the url will not need parameters but rather use the data, command and extra
data will automatically have JSON.stringify() applied
in PHP access this with $data = $_POST["data"];
often, we might store this directly as JSON in the database
but it can be split up and put in fields as follows
$assoc = json_decode($data, true); // true for assoc array if desired
command is what to do with the data and will be encodeURI sent as variable command
so for instance receive $command = $_POST["command"];
this could have a value of "select", "add", "update", "delete", etc.
extra is any extra filter information and will be encodeURI sent as variable extra
so for instance receive $extra = $_POST["extra"];
this could be an id or a search term
call is the function to call and will receive (data, error) as parameters
the data will automatically have JSON.parse() applied if in JSON format
put(url, data, call) - send and receive based on PUT
put sends data in the body of the file
the url will not have parameters but rather use the data
the data will automatically have JSON.stringify() applied
in PHP access this with: $array = json_decode(file_get_contents('php://input'), true);
call is the function to call and will receive (data, error) as parameters
the data will automatically have JSON.parse() applied if in JSON format
PROPERTIES
master - get or set the master data being sent with each get() or post() (not put())
couple - get or set whether the POST data is coupled when sent and uncoupled when received (not get() and put())
lock - get or set the lock data being sent with each get() or post() (not put())
--*///+13.8
zim.Ajax = function(master, couple, lock, unique) {
z_d("13.8");
var http = new XMLHttpRequest();
this.master = master;
this.couple = couple;
this.lock = lock;
this.unique = unique;
var that = this;
this.get = function(url, callback) {
// add here in case property is changed
var addMaster = !zot(that.master)?"&master="+encodeURI(master):"";
var addLock = !zot(that.lock)?"&lock="+encodeURI(lock):"";
var addUnique = that.unique?"&unique=true":"";
http.open('GET', url+addMaster+addLock+addUnique, true);
http.onload = function() {
if (http.status==200) {
callback(zim.isJSON(http.responseText)?JSON.parse(http.responseText):http.responseText);
} else {
callback(null, 'Error: '+http.status);
}
};
http.send();
};
this.post = function(url, data, command, extra, callback) {
var sig = "url, data, command, extra, callback";
var duo; if (duo = zob(that.post, arguments, sig)) return duo;
if (zot(url)) return;
http.open('POST', url, true);
http.setRequestHeader('Content-type', "application/x-www-form-urlencoded");
http.onload = function() {
var r = http.responseText;
if (zim.isJSON(r)) {
if (that.couple) r = zim.decouple(r);
r = JSON.parse(r);
}
callback(r);
// callback(isJSON(http.responseText)?JSON.parse(http.responseText):http.responseText);
};
if (!zim.isJSON(data)) data = JSON.stringify(data);
if (that.couple) data = zim.couple(data);
var addMaster = !zot(that.master)?"&master="+encodeURIComponent(that.master):"";
var addLock = !zot(that.lock)?"&lock="+encodeURIComponent(that.lock):"";
// var addUnique = that.unique?"&unique=true":"";
var addCommand = !zot(command)?"&command="+encodeURIComponent(command):"";
var addExtra = !zot(extra)?"&extra="+encodeURIComponent(extra):"";
http.send("data="+encodeURIComponent(data)+addMaster+addLock+addCommand+addExtra);
};
this.put = function(url, data, callback) {
http.open('PUT', url, true);
http.setRequestHeader('Content-type', 'application/json');
http.onload = function() {
callback(zim.isJSON(http.responseText)?JSON.parse(http.responseText):that.http.responseText);
};
http.send(JSON.stringify(data));
};
};//-13.8
/*--
zim.Noise = function(seed)
Noise
zim class
DESCRIPTION
Noise creates OpenSimplex Noise: https://en.wikipedia.org/wiki/OpenSimplex_noise
Converted from https://www.npmjs.com/package/open-simplex-noise
See examples at https://zimjs.com/noise/
In general, this is special noise where the pixels relate to one another in a complex way.
This connection, lets us do things like create terrains or blobs, etc. that look organic.
There is 1D, 2D, 3D, and 4D noise where we pass in one value, two values, three values and four values.
We always get back a number between -1 and 1 and this result relates to the results around it.
1D - we can plot 1D by drawing line segments across the stage (x) and setting the y value to the result of simplex1D(x)
This makes a 2D mountain-like terrain across the stage
2D - if we keep the plot from the 1D but use 2D and change the second parameter, we can animate the line.
We just need to adjust the second parameter by a very small amount each time such as .005.
Or we can plot put the return value of simplex2D onto its x,y matching location in a Bitmap
mapping it to a greyscale to make a traditional noise pattern.
We can adjust the "size" of the noise by dividing the x and y values (frequency).
If we use the ZIM smoothStep() function we can smoothen these to make blobs.
We can also use the return value as height for 3D terrain.
3D - if we keep the traditional noise/blob pattern from the 2D but use simplex3D and animate the third parameter,
we can animate the 2D noise in time which looks great when we animate blobs!
This plotting is thousands of computations and will bog the computer if too big.
4D - will allow us to animate 3D values, etc.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// 1D Noise to make a jagged line across the stage
var noise = new Noise();
var shape = new Shape(stageW, stageH).addTo(stage);
shape.graphics.s("black").ss(2).mt(0, stageH/2);
loop(stageW/50, function(i) {
shape.graphics.lt((i+1)*50, stageH/2 + noise.simplex1D(i)*200);
});
// the above can be animated by using simplex2D and animating the second number by small amounts
END EXAMPLE
EXAMPLE
// 2D noise
// create a Noise object:
var noise = new Noise();
// create an empty Bitmap size 200, 200 into which to draw the noise
var bmp = new Bitmap(null, 200, 200).center();
// we fill the bitmap starting from top left going across in the inner loop,
// then down, then across, etc. until we get to bottom right.
for (var y = 0; y < bmp.height; y++) {
for (var x = 0; x < bmp.width; x++) {
// the noise methods return a number from -1 to 1
// by adding 1 we get a number between 0 and 2 and we divide by 2 to get 0-1
// and we multiply this by 255 to get a number between 0 and 255
var value = (noise.simplex2D(x,y)+1)/2 * 255;
// imageData is one big array with four values per pixel
// the red, green, blue and alpha
// each value will constrained to between 0 and 255
// the i value is how many on the current row plus the columns from the previous rows
// and we set it to increase by 4 each time giving us a place for each color and alpha
// We write the same value for red, green, blue to get a shade of grey
var i = (x + y * bmp.width) * 4;
bmp.imageData.data[i] = value; // red (0-255)
bmp.imageData.data[i + 1] = value; // green (0-255)
bmp.imageData.data[i + 2] = value; // blue (0-255)
bmp.imageData.data[i + 3] = 255; // alpha (0-255)
}
}
bmp.drawImageData(); // this draws the imageData to the Bitmap
// Here is the same example to get blobs using smoothStep:
var f = 25; // try changing this number around
for (var y = 0; y < bmp.height; y++) {
for (var x = 0; x < bmp.width; x++) {
var value = (noise.simplex2D(x/f, y/f)+1)/2; // 0-1
// smoothStep sets less than .3 to 0 and greater than .35 to 1
// and transitions between using an easing formula in the shape of an f
var value = smoothStep(value, .3, .35) * 255;
var i = (x + y * bmp.width) * 4;
bmp.imageData.data[i] = value; // red (0-255)
bmp.imageData.data[i + 1] = value; // green (0-255)
bmp.imageData.data[i + 2] = value; // blue (0-255)
bmp.imageData.data[i + 3] = 255; // alpha (0-255)
}
}
bmp.drawImageData();
END EXAMPLE
PARAMETERS
seed - (default Math.random()*1000000) keeping the same seed can remake a pattern the same
METHODS
simplex1D(x) - returns a noise value between -1 and 1
In each method, the noise value relates to its neighbor rather than a completely random value
simplex2D(x,y) - returns a noise value between -1 and 1
simplex3D(x,y,z) - returns a noise value between -1 and 1
simplex4D(x,y,z,w) - returns a noise value between -1 and 1
PROPERTIES
seed - read only - the seed that was used for the Noise object
--*///+13.9
zim.Noise = function(seed) {
"use strict";
z_d("13.9");
if (zot(seed)) seed = Math.random()*1000000;
var clientSeed = seed;
this.seed = seed;
var that = this;
var con = {}; // holds the constants
con.NORM_2D = 1.0 / 47.0;
con.NORM_3D = 1.0 / 103.0;
con.NORM_4D = 1.0 / 30.0;
con.SQUISH_2D = (Math.sqrt(2 + 1) - 1) / 2;
con.SQUISH_3D = (Math.sqrt(3 + 1) - 1) / 3;
con.SQUISH_4D = (Math.sqrt(4 + 1) - 1) / 4;
con.STRETCH_2D = (1 / Math.sqrt(2 + 1) - 1) / 2;
con.STRETCH_3D = (1 / Math.sqrt(3 + 1) - 1) / 3;
con.STRETCH_4D = (1 / Math.sqrt(4 + 1) - 1) / 4;
con.base2D = [
[1, 1, 0, 1, 0, 1, 0, 0, 0],
[1, 1, 0, 1, 0, 1, 2, 1, 1]
];
con.base3D = [
[0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1],
[2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1, 3, 1, 1, 1],
[1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1]
];
con.base4D = [
[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1],
[3, 1, 1, 1, 0, 3, 1, 1, 0, 1, 3, 1, 0, 1, 1, 3, 0, 1, 1, 1, 4, 1, 1, 1, 1],
[
1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 2, 1, 1, 0, 0, 2, 1, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 1,
0, 2, 0, 1, 0, 1, 2, 0, 0, 1, 1
],
[
3, 1, 1, 1, 0, 3, 1, 1, 0, 1, 3, 1, 0, 1, 1, 3, 0, 1, 1, 1, 2, 1, 1, 0, 0, 2, 1, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 1,
0, 2, 0, 1, 0, 1, 2, 0, 0, 1, 1
]
];
con.gradients2D = [5, 2, 2, 5, -5, 2, -2, 5, 5, -2, 2, -5, -5, -2, -2, -5];
con.gradients3D = [
-11, 4, 4, -4, 11, 4, -4, 4, 11,
11, 4, 4, 4, 11, 4, 4, 4, 11,
-11, -4, 4, -4, -11, 4, -4, -4, 11,
11, -4, 4, 4, -11, 4, 4, -4, 11,
-11, 4, -4, -4, 11, -4, -4, 4, -11,
11, 4, -4, 4, 11, -4, 4, 4, -11,
-11, -4, -4, -4, -11, -4, -4, -4, -11,
11, -4, -4, 4, -11, -4, 4, -4, -11
];
con.gradients4D = [
3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3,
-3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3,
3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3,
-3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3,
3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3,
-3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3,
3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3,
-3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3,
3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3,
-3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3,
3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3,
-3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3,
3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3,
-3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3,
3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3,
-3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3
];
con.lookupPairs2D = [0, 1, 1, 0, 4, 1, 17, 0, 20, 2, 21, 2, 22, 5, 23, 5, 26, 4, 39, 3, 42, 4, 43, 3];
con.lookupPairs3D = [
0, 2, 1, 1, 2, 2, 5, 1, 6, 0, 7, 0, 32, 2, 34, 2, 129, 1, 133, 1, 160, 5, 161, 5, 518, 0, 519, 0, 546, 4, 550, 4, 645,
3, 647, 3, 672, 5, 673, 5, 674, 4, 677, 3, 678, 4, 679, 3, 680, 13, 681, 13, 682, 12, 685, 14, 686, 12, 687, 14, 712,
20, 714, 18, 809, 21, 813, 23, 840, 20, 841, 21, 1198, 19, 1199, 22, 1226, 18, 1230, 19, 1325, 23, 1327, 22, 1352, 15,
1353, 17, 1354, 15, 1357, 17, 1358, 16, 1359, 16, 1360, 11, 1361, 10, 1362, 11, 1365, 10, 1366, 9, 1367, 9, 1392, 11,
1394, 11, 1489, 10, 1493, 10, 1520, 8, 1521, 8, 1878, 9, 1879, 9, 1906, 7, 1910, 7, 2005, 6, 2007, 6, 2032, 8, 2033,
8, 2034, 7, 2037, 6, 2038, 7, 2039, 6
];
con.lookupPairs4D = [
0, 3, 1, 2, 2, 3, 5, 2, 6, 1, 7, 1, 8, 3, 9, 2, 10, 3, 13, 2, 16, 3, 18, 3, 22, 1, 23, 1, 24, 3, 26, 3, 33, 2, 37, 2,
38, 1, 39, 1, 41, 2, 45, 2, 54, 1, 55, 1, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 256, 3, 258, 3, 264,
3, 266, 3, 272, 3, 274, 3, 280, 3, 282, 3, 2049, 2, 2053, 2, 2057, 2, 2061, 2, 2081, 2, 2085, 2, 2089, 2, 2093, 2,
2304, 9, 2305, 9, 2312, 9, 2313, 9, 16390, 1, 16391, 1, 16406, 1, 16407, 1, 16422, 1, 16423, 1, 16438, 1, 16439, 1,
16642, 8, 16646, 8, 16658, 8, 16662, 8, 18437, 6, 18439, 6, 18469, 6, 18471, 6, 18688, 9, 18689, 9, 18690, 8, 18693,
6, 18694, 8, 18695, 6, 18696, 9, 18697, 9, 18706, 8, 18710, 8, 18725, 6, 18727, 6, 131128, 0, 131129, 0, 131130, 0,
131131, 0, 131132, 0, 131133, 0, 131134, 0, 131135, 0, 131352, 7, 131354, 7, 131384, 7, 131386, 7, 133161, 5, 133165,
5, 133177, 5, 133181, 5, 133376, 9, 133377, 9, 133384, 9, 133385, 9, 133400, 7, 133402, 7, 133417, 5, 133421, 5,
133432, 7, 133433, 5, 133434, 7, 133437, 5, 147510, 4, 147511, 4, 147518, 4, 147519, 4, 147714, 8, 147718, 8, 147730,
8, 147734, 8, 147736, 7, 147738, 7, 147766, 4, 147767, 4, 147768, 7, 147770, 7, 147774, 4, 147775, 4, 149509, 6,
149511, 6, 149541, 6, 149543, 6, 149545, 5, 149549, 5, 149558, 4, 149559, 4, 149561, 5, 149565, 5, 149566, 4, 149567,
4, 149760, 9, 149761, 9, 149762, 8, 149765, 6, 149766, 8, 149767, 6, 149768, 9, 149769, 9, 149778, 8, 149782, 8,
149784, 7, 149786, 7, 149797, 6, 149799, 6, 149801, 5, 149805, 5, 149814, 4, 149815, 4, 149816, 7, 149817, 5, 149818,
7, 149821, 5, 149822, 4, 149823, 4, 149824, 37, 149825, 37, 149826, 36, 149829, 34, 149830, 36, 149831, 34, 149832,
37, 149833, 37, 149842, 36, 149846, 36, 149848, 35, 149850, 35, 149861, 34, 149863, 34, 149865, 33, 149869, 33,
149878, 32, 149879, 32, 149880, 35, 149881, 33, 149882, 35, 149885, 33, 149886, 32, 149887, 32, 150080, 49, 150082,
48, 150088, 49, 150098, 48, 150104, 47, 150106, 47, 151873, 46, 151877, 45, 151881, 46, 151909, 45, 151913, 44,
151917, 44, 152128, 49, 152129, 46, 152136, 49, 152137, 46, 166214, 43, 166215, 42, 166230, 43, 166247, 42, 166262,
41, 166263, 41, 166466, 48, 166470, 43, 166482, 48, 166486, 43, 168261, 45, 168263, 42, 168293, 45, 168295, 42,
168512, 31, 168513, 28, 168514, 31, 168517, 28, 168518, 25, 168519, 25, 280952, 40, 280953, 39, 280954, 40, 280957,
39, 280958, 38, 280959, 38, 281176, 47, 281178, 47, 281208, 40, 281210, 40, 282985, 44, 282989, 44, 283001, 39,
283005, 39, 283208, 30, 283209, 27, 283224, 30, 283241, 27, 283256, 22, 283257, 22, 297334, 41, 297335, 41, 297342,
38, 297343, 38, 297554, 29, 297558, 24, 297562, 29, 297590, 24, 297594, 21, 297598, 21, 299365, 26, 299367, 23,
299373, 26, 299383, 23, 299389, 20, 299391, 20, 299584, 31, 299585, 28, 299586, 31, 299589, 28, 299590, 25, 299591,
25, 299592, 30, 299593, 27, 299602, 29, 299606, 24, 299608, 30, 299610, 29, 299621, 26, 299623, 23, 299625, 27,
299629, 26, 299638, 24, 299639, 23, 299640, 22, 299641, 22, 299642, 21, 299645, 20, 299646, 21, 299647, 20, 299648,
61, 299649, 60, 299650, 61, 299653, 60, 299654, 59, 299655, 59, 299656, 58, 299657, 57, 299666, 55, 299670, 54,
299672, 58, 299674, 55, 299685, 52, 299687, 51, 299689, 57, 299693, 52, 299702, 54, 299703, 51, 299704, 56, 299705,
56, 299706, 53, 299709, 50, 299710, 53, 299711, 50, 299904, 61, 299906, 61, 299912, 58, 299922, 55, 299928, 58,
299930, 55, 301697, 60, 301701, 60, 301705, 57, 301733, 52, 301737, 57, 301741, 52, 301952, 79, 301953, 79, 301960,
76, 301961, 76, 316038, 59, 316039, 59, 316054, 54, 316071, 51, 316086, 54, 316087, 51, 316290, 78, 316294, 78,
316306, 73, 316310, 73, 318085, 77, 318087, 77, 318117, 70, 318119, 70, 318336, 79, 318337, 79, 318338, 78, 318341,
77, 318342, 78, 318343, 77, 430776, 56, 430777, 56, 430778, 53, 430781, 50, 430782, 53, 430783, 50, 431000, 75,
431002, 72, 431032, 75, 431034, 72, 432809, 74, 432813, 69, 432825, 74, 432829, 69, 433032, 76, 433033, 76, 433048,
75, 433065, 74, 433080, 75, 433081, 74, 447158, 71, 447159, 68, 447166, 71, 447167, 68, 447378, 73, 447382, 73,
447386, 72, 447414, 71, 447418, 72, 447422, 71, 449189, 70, 449191, 70, 449197, 69, 449207, 68, 449213, 69, 449215,
68, 449408, 67, 449409, 67, 449410, 66, 449413, 64, 449414, 66, 449415, 64, 449416, 67, 449417, 67, 449426, 66,
449430, 66, 449432, 65, 449434, 65, 449445, 64, 449447, 64, 449449, 63, 449453, 63, 449462, 62, 449463, 62, 449464,
65, 449465, 63, 449466, 65, 449469, 63, 449470, 62, 449471, 62, 449472, 19, 449473, 19, 449474, 18, 449477, 16,
449478, 18, 449479, 16, 449480, 19, 449481, 19, 449490, 18, 449494, 18, 449496, 17, 449498, 17, 449509, 16, 449511,
16, 449513, 15, 449517, 15, 449526, 14, 449527, 14, 449528, 17, 449529, 15, 449530, 17, 449533, 15, 449534, 14,
449535, 14, 449728, 19, 449729, 19, 449730, 18, 449734, 18, 449736, 19, 449737, 19, 449746, 18, 449750, 18, 449752,
17, 449754, 17, 449784, 17, 449786, 17, 451520, 19, 451521, 19, 451525, 16, 451527, 16, 451528, 19, 451529, 19,
451557, 16, 451559, 16, 451561, 15, 451565, 15, 451577, 15, 451581, 15, 451776, 19, 451777, 19, 451784, 19, 451785,
19, 465858, 18, 465861, 16, 465862, 18, 465863, 16, 465874, 18, 465878, 18, 465893, 16, 465895, 16, 465910, 14,
465911, 14, 465918, 14, 465919, 14, 466114, 18, 466118, 18, 466130, 18, 466134, 18, 467909, 16, 467911, 16, 467941,
16, 467943, 16, 468160, 13, 468161, 13, 468162, 13, 468163, 13, 468164, 13, 468165, 13, 468166, 13, 468167, 13,
580568, 17, 580570, 17, 580585, 15, 580589, 15, 580598, 14, 580599, 14, 580600, 17, 580601, 15, 580602, 17, 580605,
15, 580606, 14, 580607, 14, 580824, 17, 580826, 17, 580856, 17, 580858, 17, 582633, 15, 582637, 15, 582649, 15,
582653, 15, 582856, 12, 582857, 12, 582872, 12, 582873, 12, 582888, 12, 582889, 12, 582904, 12, 582905, 12, 596982,
14, 596983, 14, 596990, 14, 596991, 14, 597202, 11, 597206, 11, 597210, 11, 597214, 11, 597234, 11, 597238, 11,
597242, 11, 597246, 11, 599013, 10, 599015, 10, 599021, 10, 599023, 10, 599029, 10, 599031, 10, 599037, 10, 599039,
10, 599232, 13, 599233, 13, 599234, 13, 599235, 13, 599236, 13, 599237, 13, 599238, 13, 599239, 13, 599240, 12,
599241, 12, 599250, 11, 599254, 11, 599256, 12, 599257, 12, 599258, 11, 599262, 11, 599269, 10, 599271, 10, 599272,
12, 599273, 12, 599277, 10, 599279, 10, 599282, 11, 599285, 10, 599286, 11, 599287, 10, 599288, 12, 599289, 12,
599290, 11, 599293, 10, 599294, 11, 599295, 10
];
con.p2D = [0, 0, 1, -1, 0, 0, -1, 1, 0, 2, 1, 1, 1, 2, 2, 0, 1, 2, 0, 2, 1, 0, 0, 0];
con.p3D = [
0, 0, 1, -1, 0, 0, 1, 0, -1, 0, 0, -1, 1, 0, 0, 0, 1, -1, 0, 0, -1, 0, 1, 0, 0, -1, 1, 0, 2, 1, 1, 0, 1, 1, 1, -1, 0,
2, 1, 0, 1, 1, 1, -1, 1, 0, 2, 0, 1, 1, 1, -1, 1, 1, 1, 3, 2, 1, 0, 3, 1, 2, 0, 1, 3, 2, 0, 1, 3, 1, 0, 2, 1, 3, 0, 2,
1, 3, 0, 1, 2, 1, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 0, 2, 0, 2, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 0, 0, 0, 1, 1,
-1, 1, 2, 0, 0, 0, 0, 1, -1, 1, 1, 2, 0, 0, 0, 0, 1, 1, 1, -1, 2, 3, 1, 1, 1, 2, 0, 0, 2, 2, 3, 1, 1, 1, 2, 2, 0, 0,
2, 3, 1, 1, 1, 2, 0, 2, 0, 2, 1, 1, -1, 1, 2, 0, 0, 2, 2, 1, 1, -1, 1, 2, 2, 0, 0, 2, 1, -1, 1, 1, 2, 0, 0, 2, 2, 1,
-1, 1, 1, 2, 0, 2, 0, 2, 1, 1, 1, -1, 2, 2, 0, 0, 2, 1, 1, 1, -1, 2, 0, 2, 0
];
con.p4D = [
0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 0, -1, 0, 1,
0, 0, 0, -1, 1, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 1, 0, 0, -1, 0, 1, 0, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0, 1, 1, 1, -1,
0, 1, 1, 1, 0, -1, 0, 2, 1, 0, 1, 0, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 0, 2, 0, 1, 1, 0, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1,
0, 2, 1, 0, 0, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 0, 2, 0, 1, 0, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 0, 2, 0, 0, 1, 1,
1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 1, 4, 2, 1, 1, 0, 4, 1, 2, 1, 0, 4, 1, 1, 2, 0, 1, 4, 2, 1, 0, 1, 4, 1, 2, 0, 1, 4, 1,
1, 0, 2, 1, 4, 2, 0, 1, 1, 4, 1, 0, 2, 1, 4, 1, 0, 1, 2, 1, 4, 0, 2, 1, 1, 4, 0, 1, 2, 1, 4, 0, 1, 1, 2, 1, 2, 1, 1,
0, 0, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 1, 2, 1, 0, 1, 0, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 1, 2, 0, 1, 1, 0, 3, 0, 2, 1, 0,
3, 0, 1, 2, 0, 1, 2, 1, 0, 0, 1, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 1, 2, 0, 1, 0, 1, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 1, 2,
0, 0, 1, 1, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 2, 3, 1, 1, 1, 0, 2, 1, 1, 1, -1, 2, 2, 0, 0, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1,
-1, 1, 2, 2, 0, 0, 0, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 2, 0, 0, 0, 2, 3, 1, 1, 1, 0, 2, 1, 1, 1, -1, 2, 0, 2, 0,
0, 2, 3, 1, 1, 0, 1, 2, 1, 1, -1, 1, 2, 0, 2, 0, 0, 2, 3, 0, 1, 1, 1, 2, -1, 1, 1, 1, 2, 0, 2, 0, 0, 2, 3, 1, 1, 1, 0,
2, 1, 1, 1, -1, 2, 0, 0, 2, 0, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 0, 0, 2, 0, 2, 3, 0, 1, 1, 1, 2, -1, 1, 1, 1, 2,
0, 0, 2, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1, -1, 1, 2, 0, 0, 0, 2, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 0, 0, 0, 2, 2, 3, 0,
1, 1, 1, 2, -1, 1, 1, 1, 2, 0, 0, 0, 2, 2, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 0, 0, 0, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0,
1, -1, 0, 0, 0, 0, 0, 2, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 0, 0, 0, 0, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 0, 0, 0, 0,
0, 2, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 0, 0, 0, 0, 0, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 0, 0, 0, 0, 0, 2, 1, 1, 1, -1,
0, 1, 1, 1, 0, -1, 2, 2, 0, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 2, 2, 0, 0, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1,
2, 2, 0, 0, 0, 2, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 2, 0, 2, 0, 0, 2, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 2, 0, 2, 0, 0, 2,
1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 2, 0, 2, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 2, 0, 0, 2, 0, 2, 1, -1, 1, 1, 0, 1,
0, 1, 1, -1, 2, 0, 0, 2, 0, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 2, 0, 0, 2, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 2, 0,
0, 0, 2, 2, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 2, 0, 0, 0, 2, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 2, 0, 0, 0, 2, 3, 1, 1,
0, 0, 0, 2, 2, 0, 0, 0, 2, 1, 1, 1, -1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, 1, 1, 1, -1, 3, 1, 0, 0, 1, 0, 2, 0, 0, 2,
0, 2, 1, 1, 1, -1, 3, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, 1, 1, -1, 1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, 1, 1, -1, 1,
3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, 1, 1, -1, 1, 3, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, 1, -1, 1, 1, 3, 1, 0, 0, 1, 0, 2,
0, 0, 2, 0, 2, 1, -1, 1, 1, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, 1, -1, 1, 1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, -1,
1, 1, 1, 3, 1, 0, 0, 1, 0, 2, 0, 0, 2, 0, 2, -1, 1, 1, 1, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, -1, 1, 1, 1, 3, 3, 2, 1,
0, 0, 3, 1, 2, 0, 0, 4, 1, 1, 1, 1, 3, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 4, 1, 1, 1, 1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0,
4, 1, 1, 1, 1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 4, 1, 1, 1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 4, 1, 1, 1, 1, 3, 3,
0, 0, 2, 1, 3, 0, 0, 1, 2, 4, 1, 1, 1, 1, 3, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 2, 1, 1, 1, -1, 3, 3, 2, 0, 1, 0, 3, 1, 0,
2, 0, 2, 1, 1, 1, -1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 2, 1, 1, 1, -1, 3, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 2, 1, 1, -1,
1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 2, 1, 1, -1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 2, 1, 1, -1, 1, 3, 3, 2, 0, 1, 0,
3, 1, 0, 2, 0, 2, 1, -1, 1, 1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 2, 1, -1, 1, 1, 3, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 2,
1, -1, 1, 1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 2, -1, 1, 1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 2, -1, 1, 1, 1, 3, 3,
0, 0, 2, 1, 3, 0, 0, 1, 2, 2, -1, 1, 1, 1
];
// helper classes
function shuffleSeed(seed) {
var newSeed = new Uint32Array(1);
newSeed[0] = seed[0] * 1664525 + 1013904223;
return newSeed;
}
function Contribution2(multiplier, xsb, ysb) {
this.dx = -xsb - multiplier * con.SQUISH_2D;
this.dy = -ysb - multiplier * con.SQUISH_2D;
this.xsb = xsb;
this.ysb = ysb;
}
function Contribution3(multiplier, xsb, ysb, zsb) {
this.dx = -xsb - multiplier * con.SQUISH_3D;
this.dy = -ysb - multiplier * con.SQUISH_3D;
this.dz = -zsb - multiplier * con.SQUISH_3D;
this.xsb = xsb;
this.ysb = ysb;
this.zsb = zsb;
}
function Contribution4(multiplier, xsb, ysb, zsb, wsb) {
this.dx = -xsb - multiplier * con.SQUISH_4D;
this.dy = -ysb - multiplier * con.SQUISH_4D;
this.dz = -zsb - multiplier * con.SQUISH_4D;
this.dw = -wsb - multiplier * con.SQUISH_4D;
this.xsb = xsb;
this.ysb = ysb;
this.zsb = zsb;
this.wsb = wsb;
}
// initialize
var contributions2D = [];
for (var i = 0; i < con.p2D.length; i += 4) {
var baseSet = con.base2D[con.p2D[i]];
var previous = null;
var current = null;
for (var k = 0; k < baseSet.length; k += 3) {
current = new Contribution2(baseSet[k], baseSet[k + 1], baseSet[k + 2]);
if (previous === null)
contributions2D[i / 4] = current;
else
previous.next = current;
previous = current;
}
current.next = new Contribution2(con.p2D[i + 1], con.p2D[i + 2], con.p2D[i + 3]);
}
this.lookup2D = [];
for (var i = 0; i < con.lookupPairs2D.length; i += 2) {
this.lookup2D[con.lookupPairs2D[i]] = contributions2D[con.lookupPairs2D[i + 1]];
}
var contributions3D = [];
for (var i = 0; i < con.p3D.length; i += 9) {
var baseSet = con.base3D[con.p3D[i]];
var previous = null;
var current = null;
for (var k = 0; k < baseSet.length; k += 4) {
current = new Contribution3(baseSet[k], baseSet[k + 1], baseSet[k + 2], baseSet[k + 3]);
if (previous === null)
contributions3D[i / 9] = current;
else
previous.next = current;
previous = current;
}
current.next = new Contribution3(con.p3D[i + 1], con.p3D[i + 2], con.p3D[i + 3], con.p3D[i + 4]);
current.next.next = new Contribution3(con.p3D[i + 5], con.p3D[i + 6], con.p3D[i + 7], con.p3D[i + 8]);
}
this.lookup3D = [];
for (var i = 0; i < con.lookupPairs3D.length; i += 2) {
this.lookup3D[con.lookupPairs3D[i]] = contributions3D[con.lookupPairs3D[i + 1]];
}
var contributions4D = [];
for (var i = 0; i < con.p4D.length; i += 16) {
var baseSet = con.base4D[con.p4D[i]];
var previous = null;
var current = null;
for (var k = 0; k < baseSet.length; k += 5) {
current = new Contribution4(baseSet[k], baseSet[k + 1], baseSet[k + 2], baseSet[k + 3], baseSet[k + 4]);
if (previous === null)
contributions4D[i / 16] = current;
else
previous.next = current;
previous = current;
}
current.next = new Contribution4(con.p4D[i + 1], con.p4D[i + 2], con.p4D[i + 3], con.p4D[i + 4], con.p4D[i + 5]);
current.next.next = new Contribution4(con.p4D[i + 6], con.p4D[i + 7], con.p4D[i + 8], con.p4D[i + 9], con.p4D[i + 10]);
current.next.next.next = new Contribution4(con.p4D[i + 11], con.p4D[i + 12], con.p4D[i + 13], con.p4D[i + 14], con.p4D[i + 15]);
}
this.lookup4D = [];
for (var i = 0; i < con.lookupPairs4D.length; i += 2) {
this.lookup4D[con.lookupPairs4D[i]] = contributions4D[con.lookupPairs4D[i + 1]];
}
// end initialize
this.perm = new Uint8Array(256);
this.perm2D = new Uint8Array(256);
this.perm3D = new Uint8Array(256);
this.perm4D = new Uint8Array(256);
var source = new Uint8Array(256);
for (var i = 0; i < 256; i++)
source[i] = i;
var seed = new Uint32Array(1);
seed[0] = clientSeed;
seed = shuffleSeed(shuffleSeed(shuffleSeed(seed)));
for (var i = 255; i >= 0; i--) {
seed = shuffleSeed(seed);
var r = new Uint32Array(1);
r[0] = (seed[0] + 31) % (i + 1);
if (r[0] < 0)
r[0] += (i + 1);
this.perm[i] = source[r[0]];
this.perm2D[i] = this.perm[i] & 0x0E;
this.perm3D[i] = (this.perm[i] % 24) * 3;
this.perm4D[i] = this.perm[i] & 0xFC;
source[r[0]] = source[i];
}
this.simplex1D = function(x) {
return that.simplex2D(x, 1);
};
this.simplex2D = function (x, y) {
var stretchOffset = (x + y) * con.STRETCH_2D;
var _a = [x + stretchOffset, y + stretchOffset], xs = _a[0], ys = _a[1];
var _b = [Math.floor(xs), Math.floor(ys)], xsb = _b[0], ysb = _b[1];
var squishOffset = (xsb + ysb) * con.SQUISH_2D;
var _c = [x - (xsb + squishOffset), y - (ysb + squishOffset)], dx0 = _c[0], dy0 = _c[1];
var _d = [xs - xsb, ys - ysb], xins = _d[0], yins = _d[1];
var inSum = xins + yins;
var hashVals = new Uint32Array(4);
hashVals[0] = xins - yins + 1;
hashVals[1] = inSum;
hashVals[2] = inSum + yins;
hashVals[3] = inSum + xins;
var hash = hashVals[0] | (hashVals[1] << 1) | (hashVals[2] << 2) | (hashVals[3] << 4);
var c = that.lookup2D[hash];
var value = 0.0;
while (typeof c !== 'undefined') {
var _e = [dx0 + c.dx, dy0 + c.dy], dx = _e[0], dy = _e[1];
var attn = 2 - dx * dx - dy * dy;
if (attn > 0) {
var _f = [xsb + c.xsb, ysb + c.ysb], px = _f[0], py = _f[1];
var i = that.perm2D[(that.perm[px & 0xFF] + py) & 0xFF];
var valuePart = con.gradients2D[i] * dx + con.gradients2D[i + 1] * dy;
attn *= attn;
value += attn * attn * valuePart;
}
c = c.next;
}
return value * con.NORM_2D;
};
this.simplex3D = function (x, y, z) {
var stretchOffset = (x + y + z) * con.STRETCH_3D;
var _a = [x + stretchOffset, y + stretchOffset, z + stretchOffset], xs = _a[0], ys = _a[1], zs = _a[2];
var _b = [Math.floor(xs), Math.floor(ys), Math.floor(zs)], xsb = _b[0], ysb = _b[1], zsb = _b[2];
var squishOffset = (xsb + ysb + zsb) * con.SQUISH_3D;
var _c = [x - (xsb + squishOffset), y - (ysb + squishOffset), z - (zsb + squishOffset)], dx0 = _c[0], dy0 = _c[1], dz0 = _c[2];
var _d = [xs - xsb, ys - ysb, zs - zsb], xins = _d[0], yins = _d[1], zins = _d[2];
var inSum = xins + yins + zins;
var hashVals = new Uint32Array(7);
hashVals[0] = yins - zins + 1;
hashVals[1] = xins - yins + 1;
hashVals[2] = xins - zins + 1;
hashVals[3] = inSum;
hashVals[4] = inSum + zins;
hashVals[5] = inSum + yins;
hashVals[6] = inSum + xins;
var hash = hashVals[0] | hashVals[1] << 1 | hashVals[2] << 2 | hashVals[3] << 3 | hashVals[4] << 5 |
hashVals[5] << 7 | hashVals[6] << 9;
var c = that.lookup3D[hash];
var value = 0.0;
while (typeof c !== 'undefined') {
var _e = [dx0 + c.dx, dy0 + c.dy, dz0 + c.dz], dx = _e[0], dy = _e[1], dz = _e[2];
var attn = 2 - dx * dx - dy * dy - dz * dz;
if (attn > 0) {
var _f = [xsb + c.xsb, ysb + c.ysb, zsb + c.zsb], px = _f[0], py = _f[1], pz = _f[2];
var i = that.perm3D[(that.perm[(that.perm[px & 0xFF] + py) & 0xFF] + pz) & 0xFF];
var valuePart = con.gradients3D[i] * dx + con.gradients3D[i + 1] * dy + con.gradients3D[i + 2] * dz;
attn *= attn;
value += attn * attn * valuePart;
}
c = c.next;
}
return value * con.NORM_3D;
};
this.simplex4D = function (x, y, z, w) {
var stretchOffset = (x + y + z + w) * con.STRETCH_4D;
var _a = [x + stretchOffset, y + stretchOffset, z + stretchOffset, w + stretchOffset], xs = _a[0], ys = _a[1], zs = _a[2], ws = _a[3];
var _b = [Math.floor(xs), Math.floor(ys), Math.floor(zs), Math.floor(ws)], xsb = _b[0], ysb = _b[1], zsb = _b[2], wsb = _b[3];
var squishOffset = (xsb + ysb + zsb + wsb) * con.SQUISH_4D;
var dx0 = x - (xsb + squishOffset);
var dy0 = y - (ysb + squishOffset);
var dz0 = z - (zsb + squishOffset);
var dw0 = w - (wsb + squishOffset);
var _c = [xs - xsb, ys - ysb, zs - zsb, ws - wsb], xins = _c[0], yins = _c[1], zins = _c[2], wins = _c[3];
var inSum = xins + yins + zins + wins;
var hashVals = new Uint32Array(11);
hashVals[0] = zins - wins + 1;
hashVals[1] = yins - zins + 1;
hashVals[2] = yins - wins + 1;
hashVals[3] = xins - yins + 1;
hashVals[4] = xins - zins + 1;
hashVals[5] = xins - wins + 1;
hashVals[6] = inSum << 6;
hashVals[7] = inSum + wins;
hashVals[8] = inSum + zins;
hashVals[9] = inSum + yins;
hashVals[10] = inSum + xins;
var hash = hashVals[0] | hashVals[1] << 1 | hashVals[2] << 2 | hashVals[3] << 3 | hashVals[4] << 4 | hashVals[5] << 5 |
hashVals[6] << 6 | hashVals[7] << 8 | hashVals[8] << 11 | hashVals[9] << 14 | hashVals[10] << 17;
var c = that.lookup4D[hash];
var value = 0.0;
while (typeof c !== 'undefined') {
var _d = [dx0 + c.dx, dy0 + c.dy, dz0 + c.dz, dw0 + c.dw], dx = _d[0], dy = _d[1], dz = _d[2], dw = _d[3];
var attn = 2 - dx * dx - dy * dy - dz * dz - dw * dw;
if (attn > 0) {
var _e = [xsb + c.xsb, ysb + c.ysb, zsb + c.zsb, wsb + c.wsb], px = _e[0], py = _e[1], pz = _e[2], pw = _e[3];
var i = that.perm4D[(that.perm[(that.perm[(that.perm[px & 0xFF] + py) & 0xFF] + pz) & 0xFF] + pw) & 0xFF];
var valuePart = con.gradients4D[i] * dx + con.gradients4D[i + 1] * dy + con.gradients4D[i + 2] * dz + con.gradients4D[i + 3] * dw;
attn *= attn;
value += attn * attn * valuePart;
}
c = c.next;
}
return value * con.NORM_4D;
};
};//-13.9
/*--
zim.Point = function(x, y, z, q, r, s, t, u, v, w)
Point
zim class
DESCRIPTION
Stores x, y, z, q, r, s, t, u, v, w properties.
See also createjs.Point for a Point class with more features.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var point = new Point(100, 100);
zog(point.x, point.y); // 100, 100
END EXAMPLE
PARAMETERS
x - (default 0) the x value of the point
y - (default 0) the y value of the point
z - (default 0) the z value of the point - probably not used
q - (default 0) the q value of the point - very probably not used
r - (default 0) the r value of the point - very probably not used
s - (default 0) the s value of the point - very probably not used
t - (default 0) the t value of the point - very probably not used
u - (default 0) the u value of the point - very probably not used
v - (default 0) the v value of the point - very probably not used
w - (default 0) the w value of the point - very probably not used
PROPERTIES
x - the x value of the point
y - the y value of the point
z - the z value of the point - probably not used
q - the q value of the point - very probably not used
r - the r value of the point - very probably not used
s - the s value of the point - very probably not used
t - the t value of the point - very probably not used
u - the u value of the point - very probably not used
v - the v value of the point - very probably not used
w - the w value of the point - very probably not used
--*///+13.45
zim.Point = function(x, y, z, q, r, s, t, u, v, w) {
z_d("13.45");
if (zot(x)) x = 0;
if (zot(y)) y = 0;
if (zot(z)) z = 0;
if (zot(q)) q = 0;
if (zot(r)) r = 0;
if (zot(s)) s = 0;
if (zot(t)) t = 0;
if (zot(u)) u = 0;
if (zot(v)) v = 0;
if (zot(w)) w = 0;
this.x = x;
this.y = y;
this.z = z;
this.q = q;
this.r = r;
this.s = s;
this.t = t;
this.u = u;
this.v = v;
this.w = w;
};//-13.45
/*--
zim.Bezier = function(a, b, c, d)
Bezier
zim class
DESCRIPTION
Creates data for a Cubic Bezier to give x and y at a ratio of the curve
Also gives mx and my for a modified x and y that is more evenly spaced
Thanks Ivo Wetzel - StackExchange
Used internally by zim.getCurvePoint() used by Squiggle, Blob, Beads, and animate() in path
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var a = {x:100, y:100}; // start point
var b = {x:400, y:100}; // control point for start point
var c = {x:100, y:300}; // control point for end point
var d = {x:300, y:300}; // end point
var bezier = new Bezier(a,b,c,d);
new Shape().s(black).mt(a.x,a.y).bt(b.x,b.y, c.x,c.y, d.x,d.y).addTo();
loop(10, function (i) {
// original spacing
// new Circle(5).loc(bezier.x(i/10), bezier.y(i/10));
// modified spacing to be more even
new Circle(5).loc(bezier.mx(i/10), bezier.my(i/10));
});
END EXAMPLE
PARAMETERS
// all parameters are points with x and y properties {x:val, y:val}
a - start point of Bezier curve
b - control point for the start point
c - control point for the end point
d - end point
METHODS
x(r) - the x position of a point at ratio r (0-1) on the curve
y(r) - the y position of a point at ratio r (0-1) on the curve
mx(r) - the evenly-spaced x position of a point at ratio r (0-1) on the curve
my(r) - the evenly-spaced y position of a point at ratio r (0-1) on the curve
PROPERTIES
a, b, c, d - the points passed in - each having x and y properties
--*///+13.47
zim.Bezier = function Bezier(a, b, c, d) {
z_d("13.47");
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.len = 100;
this.arcLengths = new Array(this.len + 1);
this.arcLengths[0] = 0;
var ox = this.x(0), oy = this.y(0), clen = 0;
for(var i = 1; i <= this.len; i += 1) {
var x = this.x(i * 0.01), y = this.y(i * 0.01);
var dx = ox - x, dy = oy - y;
clen += Math.sqrt(dx * dx + dy * dy);
this.arcLengths[i] = clen;
ox = x, oy = y;
}
this.length = clen;
};
zim.Bezier.prototype = {
map: function(u) {
var targetLength = u * this.arcLengths[this.len];
var low = 0, high = this.len, index = 0;
while (low < high) {
index = low + (((high - low) / 2) | 0);
if (this.arcLengths[index] < targetLength) {
low = index + 1;
} else {
high = index;
}
}
if (this.arcLengths[index] > targetLength) {
index--;
}
var lengthBefore = this.arcLengths[index];
if (lengthBefore === targetLength) {
return index / this.len;
} else {
return (index + (targetLength - lengthBefore) / (this.arcLengths[index + 1] - lengthBefore)) / this.len;
}
},
mx: function (u) {
return this.x(this.map(u));
},
my: function (u) {
return this.y(this.map(u));
},
x: function (t) {
return ((1 - t) * (1 - t) * (1 - t)) * this.a.x
+ 3 * ((1 - t) * (1 - t)) * t * this.b.x
+ 3 * (1 - t) * (t * t) * this.c.x
+ (t * t * t) * this.d.x;
},
y: function (t) {
return ((1 - t) * (1 - t) * (1 - t)) * this.a.y
+ 3 * ((1 - t) * (1 - t)) * t * this.b.y
+ 3 * (1 - t) * (t * t) * this.c.y
+ (t * t * t) * this.d.y;
}
};//-13.47
/*--
zim.Boundary = function(x, y, width, height)
Boundary
zim class
DESCRIPTION
Stores the data for a rectangle with x, y, width and height.
Can be used with ZIM drag(), gesture() for boundaries
and the Physics module for world boundary.
NOTE: A createjs.Rectangle or an object {} with x, y, width and height properties can also be used
Boundary was introduced to reduce confusion over having a ZIM Rectangle (Shape) and a CreateJS Rectangle (data)
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
new Circle(100, blue)
.center()
.drag(new Boundary(0,0,stageW,stageH));
// note: drag and gesture used to have rect parameters
// these have now been depreciated and replaced with boundary parameters
// CONTRACT
// the drag() boundary contains the registration point
// note: the gesture() boundary contains the whole shape of the object
// here, we keep the circle inside the stage by contracting the Boundary by the radius
var radius = 100;
new Circle(radius, red)
.center()
.drag(new Boundary(0,0,stageW,stageH).contract(radius));
END EXAMPLE
PARAMETERS
x - the x position of the Boundary
y - the y position of the Boundary
width - the width of the Boundary
height - the height of the Boundary
PROPERTIES
x - the x position of the Boundary
y - the y position of the Boundary
width - the width of the Boundary
height - the height of the Boundary
METHODS
contract(number|x, y, width, height) - number of pixels to make the Boundary smaller
passing in a single number will contract this on all sides
passing in two numbers will contract from horizontal and vertical accordingly
passing in four numbers will contract from the sides accordingly
note: to expand pass in a negative number
returns object for chaining
--*///+13.46
zim.Boundary = function(x, y, width, height) {
z_d("13.46");
if (zot(x) || zot(y) || zot(width) || zot(height)) return;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.contract = function(a,b,c,d) {
if (zot(a)) return this;
if (zot(b)) b = a;
if (zot(c)) {
c = a*2;
} else {
c = c+a;
}
if (zot(d)) {
d = b*2;
} else {
d = d+b;
}
this.x += a;
this.y += b;
this.width -= c;
this.height -= d;
return this;
};
};//-13.46
/*--
zim.GradientColor = function(colors, ratios, x0, y0, x1, y1)
GradientColor
zim class
DESCRIPTION
Creates data for a Linear Gradient that can be used to color ZIM Shapes
like Circle, Rectangle, Triangle, Squiggle, Blob, Flare
and therefore all ZIM component background colors, etc.
Also see ZIM RadialColor and BitmapColor classes
NOTE: the base ZIM Shape class will need gradients applied as usual
NOTE: The chainable methods for linearGradient() and radialGradient() are depricated
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// linear gradient from pink to purple across whole gradient
// with the start at 0,0 and end at 0,500 - so from top to bottom
new Rectangle(1000, 500, new GradientColor([pink,purple], [0,1], 0,0, 0,500)).addTo();
// linear gradient with 30% pink transitioning to green at half way then to 30% pure pink
// along a horizontal path from 0 to 1000 in width
// could also go diagonal for instance 0,0,1000,500
new Rectangle(1000, 500, new GradientColor([pink,green,purple], [.3,.5,.7], 0,0, 1000,0)).addTo()
END EXAMPLE
PARAMETERS
colors - an Array of colors for the gradient, can be more than two
ratios - an Array of 0-1 numbers reprenting the start position of transitions for the colors above
x0 - the x position to start the gradient
y0 - the y position to start the gradient
x1 - the x position to end the gradient
y1 - the y position to end the gradient
PROPERTIES
type - the type of color as a String
** the above parameters are all available as properties
** but will not change objects with their color already set
--*///+13.465
zim.GradientColor = function(colors,ratios, x0,y0, x1,y1) {
z_d("13.465");
this.type = "GradientColor";
this.colors = zot(colors)?["black","white"]:colors;
this.ratios = zot(ratios)?[0,1]:ratios;
this.x0 = zot(x0)?0:x0;
this.y0 = zot(y0)?0:y0;
this.x1 = zot(x1)?0:x1;
this.y1 = zot(y1)?100:y1;
};//-13.465
/*--
zim.RadialColor = function(colors, ratios, x0, y0, r0, x1, y1, r1)
RadialColor
zim class
DESCRIPTION
Creates data for a Radial Gradient that can be used to color ZIM Shapes
like Circle, Rectangle, Triangle, Squiggle, Blob, Flare
and therefore all ZIM component background colors, etc.
Also see ZIM GradientColor and BitmapColor classes
NOTE: the base ZIM Shape class will need gradients applied as usual
NOTE: The chainable methods for linearGradient() and radialGradient() are depricated
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// radial gradient from purple to pink across whole gradient
// with the start at 0,0,200 and end at 0,0,0 - so from radius to center
new Circle(200, new RadialColor([purple,pink], [0,1], 0,0,200, 0,0,0)).center();
// radial gradient from dark to light with alpha reduced
// start fading the light right away to 30% the gradient then use the dark
// move the center of the dark right and up and bigger than radius
// move the center of the light right and up and at 0
// this makes a moon with the dark shade at the bottom left
new Circle(100, new RadialColor(
["rgba(0,0,0,.2)","rgba(255,255,255,.2)"],[0,.3], 50,-30,120, 40,-40,0)
).center()
END EXAMPLE
PARAMETERS
colors - an Array of colors for the gradient, can be more than two
ratios - an Array of 0-1 numbers reprenting the start position of transitions for the colors above
x0 - the x position to start the gradient
y0 - the y position to start the gradient
r0 - the radius at the start of the gradient
x1 - the x position to end the gradient
y1 - the y position to end the gradient
r1 - the radius at the end of the gradient
PROPERTIES
type - the type of color as a String
** the above parameters are all available as properties
** but will not change objects with their color already set
--*///+13.466
zim.RadialColor = function(colors,ratios, x0,y0,r0, x1,y1,r1) {
z_d("13.466");
this.type = "RadialColor";
this.colors = zot(colors)?["black","white"]:colors;
this.ratios = zot(ratios)?[0,1]:ratios;
this.x0 = zot(x0)?0:x0;
this.y0 = zot(y0)?0:y0;
this.r0 = zot(r0)?0:r0;
this.x1 = zot(x1)?0:x1;
this.y1 = zot(y1)?100:y1;
this.r1 = zot(r1)?100:r1;
};//-13.466
/*--
zim.BitmapColor = function(image, repetition, matrix)
BitmapColor
zim class
DESCRIPTION
Creates data for a Bitmap fill from a loaded asset
that can be used to color ZIM Shapes
like Circle, Rectangle, Triangle, Squiggle, Blob, Flare
and therefore all ZIM component background colors, etc.
Also see ZIM GradientColor and RadialColor classes
NOTE: the base ZIM Shape class will need a bitmap fill applied as usual
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var assets = "flecks.jpg";
var path = "assets/";
var frame = new Frame(scaling, width, height, color, outerColor, assets, path);
frame.on("ready", function() {
new Rectangle(frame.width, frame.height, new BitmapColor("flecks.jpg")).addTo();
// or use asset("flecks.png") instead of string "flecks.jpg" - but ZIM will figure it out
stage.update()
}
END EXAMPLE
PARAMETERS
image - a ZIM Bitmap() such as available with asset()
when asset is loaded with ZIM Frame or frame.loadAssets()
also accepts the string name of an asset that would go in asset()
may accept url to html image but image needs to be loaded first
so would recommend usual ZIM asset loading
repetition - (default "repeat") the repeat of the Bitmap fill
also "repeat-x", "repeat-y" or "no-repeat"
matrix - a transformation matrix to apply to the Bitmap
PROPERTIES
type - the type of color as a String
** the above parameters are all available as properties
** but will not change objects with their color already set
--*///+13.467
zim.BitmapColor = function(image, repetition, matrix) {
z_d("13.467");
this.type = "BitmapColor";
if (typeof image == "string" && window.asset) image = window.asset(image);
if (image.type == "Image") image = image.bitmap;
this.image = image.type=="Bitmap"?image.image:image;
this.repetition = repetition;
this.matrix = matrix;
};//-13.467
/*--
zim.Damp = function(startValue, damp)
Damp
zim class
DESCRIPTION
Damping emulates things slowing down due to friction.
The movement heads towards the right value and looks organic.
This is similar if not the same as easing out when tweening.
Create your Damp object outside an interval or Ticker
then inside an interval or ticker call the convert method.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var d = new Damp(parameters);
setInterval(function() {
dampedValue = d.convert(desiredValue);
}, 100);
END EXAMPLE
you would then apply that desired value to a property such as x or y or scale
if you want to do both x and y then you need two Damp objects
and two convert calls (you can do both in one interval or ticker)
EXAMPLE
var circle = new Circle();
circle.center();
var dampX = new Damp(circle.x);
var dampY = new Damp(circle.y);
// start moving once mouse enters stage
// this event will only run once (the last parameter is true)
stage.on("stagemousemove", start, null, true);
function start(e) {
Ticker.add(function() {
circle.x = dampX.convert(e.stageX);
circle.y = dampY.convert(e.stageY);
}, stage);
}
END EXAMPLE
PARAMETERS supports DUO - parameters or single object with properties below
startValue - (default 0) start object at this value and then start damping
damp - (default .1) the damp value with 1 being no damping and 0 being no movement
METHODS
convert(value) - converts a value into a damped value
immediate(value) - immediately goes to value and returns the Damp object
PROPERTIES
damp - can dynamically change the damping (usually just pass it in as a parameter to start)
lastValue - setting this would go immediately to this value (would not normally use)
--*///+14
zim.Damp = function(startValue, damp) {
z_d("14");
var sig = "startValue, damp";
var duo; if (duo = zob(zim.Damp, arguments, sig, this)) return duo;
this.lastValue = (zot(startValue)) ? 0 : startValue;
this.damp = (zot(damp)) ? .1 : damp;
};
zim.Damp.prototype.convert = function(desiredValue) {
return this.lastValue = this.lastValue + (desiredValue - this.lastValue) * this.damp;
};
zim.Damp.prototype.immediate = function(desiredValue) {
this.lastValue = desiredValue;
return this;
};//-14
/*--
zim.Proportion = function(baseMin, baseMax, targetMin, targetMax, factor, targetRound, clamp)
Proportion
zim class
DESCRIPTION
Proportion converts an input value to an output value on a different scale.
(sometimes called a map() function)
For instance, like a slider controlling the scale of an object or sound volume.
Make a Proportion object and then in an interval, ticker or event,
convert the base value to the target value using the convert method.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
frame.loadAssets("mySound.mp3");
frame.on("complete", function() {
var sound = frame.asset("mySound.mp3").play();
var p = new Proportion(0, 10, 0, 1);
var dial = new Dial(); // default range of 0 to 10
dial.currentValue = 10;
dial.on("change", function(){
sound.volume = p.convert(dial.currentValue);
}); // end of dial change
}); // end sound loaded
END EXAMPLE
PARAMETERS supports DUO - parameters or single object with properties below
baseMin - min for the input scale (say x value)
baseMax - max for the input scale (say x value)
targetMin - (default 0) min for the output scale (say volume)
targetMax - (default 1) max for the output scale (say volume)
factor - (default 1) is going the same direction and -1 is going in opposite direction
targetRound - (default false) set to true to round the converted number
clamp - (default true) set to false to let results go outside min and max range
METHODS
convert(input) - will return the output property (for instance, a volume)
NOTE: the object always starts by assuming baseMin as baseValue
just call the convert method right away if you want it to start at a different baseValue
for instance, if your slider went from 100 to 500 and you want to start at half way
make the object and call p.convert(300); on the next line
--*///+15
zim.Proportion = function(baseMin, baseMax, targetMin, targetMax, factor, targetRound, clamp) {
var sig = "baseMin, baseMax, targetMin, targetMax, factor, targetRound, clamp";
var duo; if (duo = zob(zim.Proportion, arguments, sig, this)) return duo;
z_d("15");
// factor - set to 1 for increasing and -1 for decreasing
// round - true to round results to whole number
if (zot(targetMin)) targetMin = 0;
if (zot(targetMax)) targetMax = 1;
if (zot(factor)) factor = 1;
if (zot(targetRound)) targetRound = false;
if (zot(clamp)) clamp = true;
// proportion
var baseAmount;
var proportion;
var targetAmount;
baseAmount = baseMin; // just start at the min otherwise call immediate(baseValue);
this.convert = function(baseAmount) {
if (isNaN(baseAmount) || (baseMax-baseMin==0)) {return;}
if (clamp) {
baseAmount = Math.max(baseAmount, baseMin);
baseAmount = Math.min(baseAmount, baseMax);
}
proportion = (baseAmount - baseMin) / (baseMax - baseMin);
if (factor > 0) {
targetAmount = targetMin + (targetMax-targetMin) * proportion;
} else {
targetAmount = targetMax - (targetMax-targetMin) * proportion;
}
if (targetRound) {targetAmount = Math.round(targetAmount);}
return targetAmount;
};
};//-15
/*--
zim.ProportionDamp = function(baseMin, baseMax, targetMin, targetMax, damp, factor, targetRound, clamp)
ProportionDamp
zim class
DESCRIPTION
ProportionDamp converts an input value to an output value on a different scale with damping.
Works like Proportion Class but with a damping parameter.
Damping needs constant calculating so do not put in mousemove event.
The below example scales the circle based on the mouse height.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var circle = new Circle(50, "red");
circle.center(); // center method added in ZIM 4TH
var pd = new ProportionDamp(0, stageH, 0, 5, .2);
Ticker.add(function() {
circle.sca(pd.convert(stage.mouseH)); // scale method added in ZIM 4TH
}, stage);
END EXAMPLE
PARAMETERS supports DUO - parameters or single object with properties below
baseMin - min for the input scale (say x value)
baseMax - max for the input scale (say x value)
targetMin - (default 0) min for the output scale (say volume)
targetMax - (default 1) max for the output scale (say volume)
damp - (default .1) the damp value with 1 being no damping and 0 being no movement
factor (default 1) is going the same direction and -1 is going in opposite direction
targetRound (default false) set to true to round the converted number
METHODS
convert(input) - converts a base value to a target value
immediate(input) - immediately sets the target value (no damping) and returns the ProportionDamp object
dispose() - clears interval
PROPERTIES
damp - can adjust this dynamically (usually just pass it in as a parameter to start)
NOTE: the object always starts by assuming baseMin as baseValue
if you want to start or go to an immediate value without easing then
call the pd.immediate(baseValue) method with your desired baseValue (not targetValue)
--*///+16
zim.ProportionDamp = function(baseMin, baseMax, targetMin, targetMax, damp, factor, targetRound, clamp) {
var sig = "baseMin, baseMax, targetMin, targetMax, damp, factor, targetRound, clamp";
var duo; if (duo = zob(zim.ProportionDamp, arguments, sig, this)) return duo;
z_d("16");
// damp - can be changed via damp get/set method property
// factor - set to 1 for increasing and -1 for decreasing
// round - true to round results to whole number
// zot() is found in danzen.js (the z version of not)
if (zot(targetMin)) targetMin = 0;
if (zot(targetMax)) targetMax = 1;
if (zot(damp)) damp = .1;
if (zot(factor)) factor = 1;
if (zot(targetRound)) targetRound = false;
if (zot(clamp)) clamp = true;
this.damp = damp; // want to expose as a property we can change
var that = this;
// proportion
var baseAmount;
var proportion;
var targetDifference;
var targetAmount;
// damping
var differenceAmount;
var desiredAmount=0;
var lastAmount = 0;
baseAmount = baseMin; // just start at the min otherwise call immediate(baseValue);
lastAmount = targetMin;
var interval = setInterval(calculate, 20);
function calculate() {
if (isNaN(baseAmount) || (baseMax-baseMin==0)) {return;}
if (clamp) {
baseAmount = Math.max(baseAmount, baseMin);
baseAmount = Math.min(baseAmount, baseMax);
}
proportion = (baseAmount - baseMin) / (baseMax - baseMin);
targetDifference = targetMax - targetMin;
if (factor > 0) {
targetAmount = targetMin + targetDifference * proportion;
} else {
targetAmount = targetMax - targetDifference * proportion;
}
desiredAmount = targetAmount;
differenceAmount = desiredAmount - lastAmount;
lastAmount += differenceAmount*that.damp;
}
this.immediate = function(n) {
that.convert(n);
calculate();
lastAmount = targetAmount;
if (targetRound) {lastAmount = Math.round(lastAmount);}
return that;
};
this.convert = function(n) {
baseAmount = n;
if (targetRound) {
return Math.round(lastAmount);
} else {
return lastAmount;
}
};
this.dispose = function(a,b,disposing) {
clearInterval(interval);
return true;
};
};//-16
/*--
zim.Dictionary = function(unique)
Dictionary
zim class
DESCRIPTION
An object that uses objects as keys to give values.
Similar to an object literal with properties except the property names are objects instead of strings.
JavaScript currently does not have a dictionary, but other languages do.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var o = {test:"test"};
var f = function(w) {zog(w)};
var c = new Circle();
var d = new Dictionary();
d.add(o, 1); d.add(f, 2); d.add(c, f);
zog(d.at(o)); // 1
zog(d.at(f)); // 2
d.at(c)("hello"); // hello
d.remove(o); // to clear o
zog(d.length); // 2
END EXAMPLE
EXAMPLE
var d = new Dictionary();
d.add(circle, "one");
d.add(circle, "two");
zog(d.at(circle)); // two - just the latest but "one" is still there
for (var i=0; i -1) return values[i];
return null;
};
this.remove = function(o) {
if (zot(o)) return false;
var i = objects.indexOf(o);
if (i > -1) {
objects.splice(i,1);
values.splice(i,1);
this.length--;
return true;
} else {
return false;
}
};
this.clear = function() {
objects = this.objects = []; // store objects and values in synched arrays
values = this.values = [];
this.length = null;
return this;
};
this.dispose = function(a,b,disposing) {
objects = null;
values = null;
this.length = null;
return true;
};
};//-17
/*--
zim.Hierarchy = function(input)
Hierarchy
zim class
DESCRIPTION
A hierarchy is a nested structure for organized data (like XML).
For instance, Hierarchy manages the accordion feature of ZIM List()
where the list can be expanded and collapsed to show nested sections.
HOW IT WORKS
There are two formats that can be used as input.
Each will create a data property in final hierarchy format.
A. The SIMPLE input is an easier format to write but
has a limitation in that identifiers must be strings.
The Hierarchy replaces the identifiers with sequential ids
and stores the original identifiers as an obj property.
B. The COMPLEX input starts off like the final hierarchy data
which has the advantage of storing any type of object in the hierarchy.
The disadvantage is the ids must be hand coded and it is longer.
The Hierarchy will add level, open and opened properties
and create the data property in final hierarchy format.
STRATEGY
The complex format is tricky.
One way to deal with it is to pass in a SIMPLE string version.
Then replace the strings with final objects in the data property.
The Hierarchy class is used internally by ZIM so may not be needed.
However, it will help for custom tree menus, mindmaps, etc.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE - SIMPLE INPUT
// 1. Here is linear input as an array - a boring tree - more like grass!
var simple = [1,2,3,4]; // so we would probably not use Hierarchy for this.
// 2. To hold nested data we use an object literal.
// The properties can hold linear arrays as values
// but if any of the values need to hold more values then use an object literal:
var simple = {
"linear":[1,2,3,4], // an array is okay as all items are leaf nodes (end nodes)
"nested":{ // an object literal is required as one or more items hold other items
"A":[], // this holds nothing (a leaf node) but still needs an empty array
"B":["one", "two", "three"], // this holds a linear list - all leaf nodes
"C":{ // this holds another nested list where at least one item holds more
"LEAF":[],
"LINEAR":[1,2,3,4],
"LEAF":[]
}
}
}
// If EXTRA info is desired this can be handled like so:
// Set the values as a list property of an object and add any extra properties desired
// The extra property does not have to be called extra and there can be multiple extra properties
// Avoid calling the properties list, obj, level, open or opened.
// The extra properties will be added to the complex data objects (see below)
var simple = {
"linear":{list:[1,2,3,4], extra:"val"},
"nested":{list:{ // an object literal is required as one or more items hold other items
"A":[], // this holds nothing (a leaf node) but still needs an empty array
"B":["one", "two", "three"], // this holds a linear list - all leaf nodes
"C":{ // this holds another nested list where at least one item holds more
"LEAF":[],
"LINEAR":[1,2,3,4],
"LEAF":[]
}
}, extra:"val"}
}
// pass the object into the input parameter:
var hierarchy = new Hierarchy(simple);
var data = hierarchy.data;
// data will be the following - note it is a more complex format
// but also a form that could hold any type of data as a value
// note the level matches the indent and all values have an id
data = {
id0:{obj:"linear", level:0, open:false, opened:false, list:{
id1:{obj:1, level:1},
id2:{obj:2, level:1},
id3:{obj:3, level:1},
id4:{obj:4, level:1}
}, extra:"val"},
id5:{obj:"nested", level:0, open:false, opened:false, list:{
id6:{obj:"A", level:1},
id7:{obj:"B", level:1, open:false, opened:false, list:{
id8:{obj:"one", level:2},
id9:{obj:"two", level:2},
id10:{obj:"three", level:2}
}},
id11:{obj:"C", level:1, open:false, opened:false, list:{
id12:{obj:"LEAF", level:2},
id13:{obj:"LINEAR", level:2, open:false, opened:false, list:{
id14:{obj:1, level:3},
id15:{obj:2, level:3},
id16:{obj:3, level:3},
id17:{obj:4, level:3}
}},
id18:{obj:"LEAF", level:2}
}}
}, extra:"val"}
}
END EXAMPLE
EXAMPLE - COMPLEX INPUT
// Here is a sample of passing in the more complex format.
// level, open, opened properties are not required
// they will be added by the Hierarchy.
// Note that there are no arrays in this data format so that each item has an id.
// This could be passed in to the data property of List
// to show an expandable hierarchy of objects rather than strings converted to buttons
var complex = {
id0:{obj:new Rectangle(), list:{
id1:{obj:new Triangle()},
id2:{obj:new Triangle()},
id3:{obj:new Triangle()}
}},
id4:{obj:new Circle(), list:{
id5:{obj:new Button()},
id6:{obj:new Button(), list:{
id7:{obj:new CheckBox()},
id8:{obj:new CheckBox()},
}},
id9:{obj:new Button(), list:{
id10:{obj:new Label("Leaf")},
id11:{obj:new Label("Nest"), list:{
id12:{obj:1},
id13:{obj:2},
id14:{obj:3},
id15:{obj:4},
}},
id16:{obj:new Label("Leaf")}
}}
}}
};
var hierarchy = new Hierarchy(complex);
var list = new List({list:hierarchy.data, align:"center"}).center();
END EXAMPLE
PARAMETERS
input (default null) - a simple formated input - see the examples
this will be turned in to a more complex object literal available as the data property
OR input a complex formated input - similar to the data property output
but only ids, obj and list properties are required.
The main purpose of Hierarchy is to create the complex data object
but passing in a complex format allows objects other than strings to be used.
METHODS
processSimple(input) - enter simple input - returns a Hierarchy data object literal
this is what the Hierarchy does when a simple input is provided to make its data property
the input must be in the simple format as described in the SIMPLE example.
processComplex(input) - enter complex input - returns a Hierarchy data object literal
this is what the Hierarchy does when complex data is provided to make its data property
processComplex will add level, open, and opened properties to the data
otherwise data must be in the same format as the final data property - see COMPLEX example
getLinearList(list) - enter final list from the data format, to get a linear list of top level objects
and all open list objects within according to the open property
getLinearIds(list) - enter final list from the data format, to get a linear list of top level ids
and all open lists ids within according to the open property
getData(id) - find the final data format for a given Hierarchy ID - eg. id0, id12, etc.
pass the data.list to the getLinearList() and getLinearIDs() methods
getNextSibling(id) - gets the id of the next sibling - skipping ids of any children
will find parents next sibling if last child in parent
or undefined if last child in hierarchy
getPrevSibling(id) - gets the id of the previous sibling - skipping ids of any children
will find the parent if first child in parent
or undefined if first child in hierarchy
PROPERTIES
data - a hierarchy formated object literal with ids that hold object literals
ids are in the format of id0, id1, id2, etc. numbered in order of creation (top to bottom)
the object literals have obj, level, open, opened and list properties
leaf nodes (end nodes) will have {} as its list property value
length - read only total length of all nodes
--*///+17.5
zim.Hierarchy = function(input, open) {
z_d("17.5");
var that = this;
if (zot(input)) return;
if (zot(open)) open = false;
var _length;
that.processSimple = function(list) {
var count = 0;
var m = {};
function makeLevel(list, obj, level, last) {
if (list.constructor == {}.constructor) {
var originalList;
if (list.list) { // in extra format
originalList = list;
list = list.list;
}
if (last && originalList) {
zim.loop(originalList, function (k,v) {
if (k=="list") return; // like a for loop continue
last[k] = v;
});
}
zim.loop(list, function (key, val) {
var newList = {};
var current = obj["id"+count] = {obj:key, level:level, open:open, opened:false, list:newList};
count++;
makeLevel(val, newList, level+1, current);
});
} else if (Array.isArray(list)) {
zim.loop(list, function (val) {
var newList = {};
obj["id"+count] = {obj:val};
count++;
});
}
}
makeLevel(input, m, 0);
_length = count;
return m;
};
that.processComplex = function(input) {
var count = 0;
function innerFunction(inp, level) {
zim.loop(inp, function (key, val) {
val.level = level;
if (zot(val.open)) val.open = open;
if (zot(val.opened)) val.opened = false;
if (val.list) innerFunction(val.list, level+1);
count++;
});
}
innerFunction(input, 0);
_length = count;
return input;
};
if (zot(input.id0)) {
that.data = that.processSimple(input);
} else {
that.data = that.processComplex(input);
}
that.getLinearList = function(data) {
if (zot(data)) data = that.data;
return getLinear(data)[0];
};
that.getLinearIDs = function(data) {
if (zot(data)) data = that.data;
return getLinear(data)[1];
};
function getLinear(data) {
var linear = [];
var ids = [];
function getLevel(data, level) {
zim.loop(data, function (item, list) {
linear.push(list.obj);
ids.push(item);
if (list.open) getLevel(list.list, level+1);
});
}
getLevel(data, 0);
return [linear, ids];
}
that.getData = function(id) {
// recursively find the data for id
var answer;
function find(obj) {
zim.loop(obj, function (key, val) {
if (key == id) {
answer = val;
return answer;
}
find(val.list);
});
}
find(that.data);
return answer;
};
that.getNextSibling = function(id) {
var current;
var answer;
function find(obj) {
zim.loop(obj, function (key, val) {
if (!answer && current) {
answer = key;
return answer;
}
if (key == id) {
current = val;
} else {
find(val.list);
}
});
}
find(that.data);
return answer;
};
that.getPrevSibling = function(id) {
var lasts = [];
var answer;
function find(obj, lev) {
zim.loop(obj, function (key, val) {
if (key == id) {
answer = lasts[lev] || lasts[lev-1];
return answer;
} else {
lasts[lev] = key;
find(val.list, lev+1);
}
});
}
find(that.data, 0);
return answer;
};
Object.defineProperty(that, 'length', {
get: function() {
return _length;
},
set: function(value) {
if (zon) zogy("Hierarchy() - length is read only");
}
});
};//-17.5
/*--
zim.Pick = function(choices)
Pick
zim class
HISTORY
Pick was originally zik() and ZIM VEE (introduced in ZIM 5) throughout the ZIM documentation
It was so handy that a general (non ZIM centric) name has been given to a class
that can be used by other libraries and languages.
See https://github.com/danzen/Pick for the complete general code and description
DESCRIPTION
Pick() provides a system to handle dynamic parameters.
It does so by providing formats for options and a choose() method to pick from the options.
For example, a particle emitter has an obj parameter to receive what type of particle to emit.
If a particle were randomly chosen from a rectangle, circle or triangle and passed into obj
then the emitter would only emit the randomly chosen particle - say, a bunch of triangles.
What is desired is that the emitter emit rectangles, circles and triangles randomly.
Pick() provides a way to pass in all three shapes and have the emitter choose each time it emits.
FORMATS
The Pick() formats handle:
1. a random selection: ["blue", "green", "yellow"] - array format
2. a random range: {min:10, max:30} - range object format
3. a series: series(10,20,30) - series format also Pick.series()
4. a function result: function(){return new Date().minutes} - function format
5. a normal value: 7 or "hello" - single-value format
6. a noPick object: {noPick:["real", "array"]} - escape format
7. a combination: [{min:10, max:20}, 30, 40] - combination format (recursive)
NOTE: the range format gets passed to ZIM rand() directly so see docs there
there are also integer and negative parameters both defaulting to false
PICK LITERAL
Formats are passed in to a Pick() object and the Pick object can be passed to a class or function parameter
In ZIM, the formats may be passed directly into the class or function parameter (as a Pick literal)
new Circle(new Pick([10,20]), red); // Pick()
new Circle([10,20], red); // Pick Literal
** The literal can run into conflicts such as for a ZIM corner parameter which accepts an array []
This would be avoided with a system always using Pick() and never the literal.
But... ZIM started off without the formalized Pick - and the literal is shorter ;-)
The conflict can be resolved by using {noPick:[]} and then the array is not picked from.
NOTE: Pick is used internally by by zim.interval, zim.animate, zim.Emitter, zim.Pen, etc.
as well as ZIM Shape basic parameters handy for cloning with Tile, Emitter, etc.
EXAMPLE
var loopCount = new Pick([1,2,3]);
var choice = Pick.choose(loopCount); // 1, 2, or 3
var loopCount = [1,2,3]; // Pick literal
var choice = Pick.choose(loopCount); // 1, 2, or 3
var choice = Pick.choose([1,2,3]); // 1, 2, or 3
var rotation = {min:10, max:20, integer:false, negative:true};
// an example of a Range object - this will give values between -20 and -10 or 10 and 20
// rotation now holds an object as to how to pick its value
// this can be passed into a zim.Emitter() for instance
// which will make multiple copies and rotate them based on Pick.choose()
// or this can be passed into an animation object
// and then into zim.Emitter() for the animate parameter
var emitter = new zim.Emitter({
obj:new Rectangle(),
random:{rotation:rotation} // the emitter will use Pick.choose() to pick a rotation for each particle
});
function age() {
// assuming user.age is some input value that exists
if (user.age >= 18) return ["a", "b", ["c","d"]];
else return ["e", "f"];
}
// below will be a, b, c or d if user is 18+ with a and b having more of a chance
// or e or f if not over 18
var show = Pick.choose(age);
// below we randomize the tile colors in the first example
// and make them in color order for the second example
new Tile(new Rectangle(10,10,["blue", "red"]), 10, 10).center(); would randomize colors
new Tile(new Rectangle(10,10,series("blue", "red")), 10, 10).center(); would alternate colors
// here we pass an array through without processing the array:
Pick.choose({noPick:[1,2,3,4,5]}); // result is [1,2,3,4,5]
// a range between one and three seconds - repeating after 3 choices
var pick = new Pick({min:1, max:3}).num(3);
interval(pick, function () {console.log("calling");}); // eg. 2.5s, 2.7s, 1.2s, 2.5s, 2.7s, 1.2s, etc.
END EXAMPLE
PARAMETERS
choices - any of the ZIM Pick formats:
1. an array of choices to choose from randomly
2. a range object with min and max (integer and negative) properties
3. a zim.series() or Pick.series() to pick objects in order
4. a function that returns a result
5. a single not one of the above that passes through
6. an escape object with a noPick property
7. any combination of the above to pick recursively
METHODS
num(number) - a chainable method to limit the number of options until Pick.choose() will repeat like a series
loop(number, call(value, index, total)) - a way to loop through options
number is the number of times to loop
call is a callback function that gets called each loop
the callback will recieve a value (the choice), the index of the loop and the total (the number parameter)
inside the function a return is like a continue and a return of any value is like a break in traditional for loops.
STATIC METHODS
Pick.choose(Pick Object or Pick Literal) - gets a value from the Pick object or Pick Literal
so chooses from a random array, or range, or gets the next in the series, etc.
Pick.rand(a, b, integer, negative) - gets a random number - same as zim.rand()
a - the first Number for the range
if a and b are not provided, rand() acts like Math.random()
if parameter b is not provided, rand will use range 0 to and including a
b - (default 0) second Number for the range
it does not matter if a>b or a= steps) {
window.scrollTo(zim["scroll"+perpend](), num);
clearInterval(scrollInterval);
}
}, interval);
}
return num;
};//-20
/*--
zim.windowWidth = function()
windowWidth
zim function
DESCRIPTION
Returns the width of a window.
(window.clientWidth or window.innerWidth)
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
if (windowWidth() < 500) zss("related").display = "none";
END EXAMPLE
RETURNS a Number
--*///+21
zim.windowWidth = function() {
z_d("21");
var w = isNaN(window.innerWidth) ? window.clientWidth : window.innerWidth;
var h = isNaN(window.innerHeight) ? window.clientHeight : window.innerHeight;
if (zim.mobile() && !zot(window.orientation) && !window.parent) {
if ((w > h && Math.abs(window.orientation) != 90) || h > w && Math.abs(window.orientation) == 90) {
var oldW = w;
w = h;
h = oldW;
}
}
// 6. part of TEN PATCH
// pay attention to swapRotation from Frame
return (typeof zdf != "undefined" && zdf.swapRotation)?h:w;
};//-21
/*--
zim.windowHeight = function()
windowHeight
zim function
DESCRIPTION
Returns the height of a window.
(window.clientHeight or window.innerHeight)
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
if (windowHeight() > 1000) zgo("big.html");
END EXAMPLE
RETURNS a Number
--*///+22
zim.windowHeight = function() {
z_d("22");
var w = isNaN(window.innerWidth) ? window.clientWidth : window.innerWidth;
var h = isNaN(window.innerHeight) ? window.clientHeight : window.innerHeight;
if (zim.mobile() && !zot(window.orientation) && !window.parent) {
if ((w > h && Math.abs(window.orientation) != 90) || h > w && Math.abs(window.orientation) == 90) {
var oldW = w;
w = h;
h = oldW;
}
}
// 7. part of TEN PATCH
// pay attention to swapRotation from Frame
return (typeof zdf != "undefined" && zdf.swapRotation)?w:h;
};//-22
/*--
zim.getQueryString = function(string)
getQueryString
zim function
DESCRIPTION
Turns the HTML query string into a object.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// currentHTML page myPage.html?party=true&toys=many
var details = getQueryString();
zog(details.party); // "true"
zog(details.toys); // "many"
loop(details, function(key, val, i) {
zog(key, val, i);
});
// outputs:
// party true 0
// toys many 1
END EXAMPLE
EXAMPLE
// an array of values is created if a query string has multiple properties with the same name:
var collection = getQueryString("type=dog&age=10&age=20&age=30");
zog(collection.age); // [10,20,30]
END EXAMPLE
PARAMETERS
string - (default null) null will get string from end of HTML page after ?
set the key value pairs (without question mark) to parse a custom string
eg. party=true&toys=many
RETURNS an object literal with properties matching the keys and values matching the values (or undefined if no query string)
--*///+22.5
zim.getQueryString = function(s) {
z_d("22.5");
if (zot(s)) s = location.search.replace("?","");
if (s == "") return {};
var vars = s.split("&");
var obj = {};
for (var i=0; i= 4.3.0 requires createjs namespace to be loaded (import createjs before zim)");} return zim;}
//////////////// ZIM DISPLAY //////////////
// Zim Display (formerly Zim Build) adds common display classes for Zapps (apps, art, games and gadgets with ZIM)
// classes in this module require createjs namespace to exist and in particular easel.js
// available at http://createjs.com
// SUBSECTION BASE DISPLAY
/*--
zim.Coordinates = function(canvasID)
Helper functions for localToGlobal, globalToLocal and localToLocal
--*///+50.43
zim.localToGlobal = function localToGlobal(x,y,scope,func) {
if (!zim.coordinatesCheck) {z_d("50.43"); zim.coordinatesCheck=true;}
if (x==null || y==null) return;
var point = func.call(scope,x,y);
var stage = scope.stage;
if (typeof zdf == "undefined") {
if (!stage) return point;
zdf = {stage:stage, canvas:stage.canvas};
}
point.x /= zim.scaX;
point.y /= zim.scaY;
return point;
};
zim.globalToLocal = function globalToLocal(x,y,scope,func) {
if (!zim.coordinatesCheck) {z_d("50.43"); zim.coordinatesCheck=true;}
if (x==null || y==null) return;
var stage = scope.stage;
if (typeof zdf == "undefined") {
if (!stage) return func.call(scope,x,y);
zdf = {stage:stage, canvas:stage.canvas};
}
x *= zim.scaX;
y *= zim.scaY;
var point = func.call(scope,x,y);
return point;
};
zim.localToLocal = function localToLocal(x,y,target,scope) {
if (!zim.coordinatesCheck) {z_d("50.43"); zim.coordinatesCheck=true;}
if (x==null || y==null || target==null) return;
var point = scope.localToGlobal(x,y);
var stage = scope.stage;
if (typeof zdf == "undefined") {
if (!stage) return target.globalToLocal(point.x, point.y);
zdf = {stage:stage, canvas:stage.canvas};
}
if (!stage) stage = zdf.stage;
if (target == stage) return point;
if (point) return target.globalToLocal(point.x, point.y);
};
//-50.43
/*--
zim.displayBase = function()
displayBase
zim function
DESCRIPTION
Used internally by ZIM to set common properties on basic DisplayObjects
Container, Shape, Bitmap, Sprite, MovieClip
Also called by zimify() if object does not already have these (hueBatch used for test)
Turns off and on allowDefault if allowDefault is true as object is interacted with
this prevents the page from scrolling on mobile when drag, gesture, transform, etc. are happening
Might have set these on CreateJS DisplayObject
--*///+50.432
zim.displayBase = function(obj) {
if (!zim.zimDBCheck) {z_d("50.432"); zim.zimDBCheck=true;}
var that = obj;
Object.defineProperty(obj, 'width', {
enumerable: true,
get: function() {
// that.setBounds(null);
var b = this.getBounds();
return (zot(b))?null:Math.abs(b.width*this.scaleX);
},
set: function(value) {
var b = this.getBounds();
if (zot(b) || b.width==0) {
if (zon) zogy("DisplayObject() - width needs bounds set with setBounds()");
return;
}
var s = value/b.width;
this.scaleX = this.scaleY = s;
}
});
Object.defineProperty(obj, 'height', {
enumerable: true,
get: function() {
// that.setBounds(null);
var b = this.getBounds();
return (zot(b))?null:Math.abs(b.height*this.scaleY);
},
set: function(value) {
var b = this.getBounds();
if (zot(b) || b.height==0) {
if (zon) zogy("DisplayObject() - height needs bounds set with setBounds()");
return;
}
var s = value/b.height;
this.scaleX = this.scaleY = s;
}
});
Object.defineProperty(obj, 'widthOnly', {
enumerable: true,
get: function() {
// that.setBounds(null);
var b = this.getBounds();
return (zot(b))?null:Math.abs(b.width*this.scaleX);
},
set: function(value) {
var b = this.getBounds();
if ((zot(b) || b.width==0) && zon) {zogy("DisplayObject() - widthOnly needs bounds set with setBounds()"); return;}
var s = value/b.width;
this.scaleX = s;
}
});
Object.defineProperty(obj, 'heightOnly', {
enumerable: true,
get: function() {
// that.setBounds(null);
var b = this.getBounds();
return (zot(b))?null:Math.abs(b.height*this.scaleY);
},
set: function(value) {
var b = this.getBounds();
if ((zot(b) || b.height==0) && zon) {zogy("DisplayObject() - heightOnly needs bounds set with setBounds()"); return;}
var s = value/b.height;
this.scaleY = s;
}
});
Object.defineProperty(obj, 'level', {
enumerable: true,
get: function() {
if (this.parent) return this.parent.getChildIndex(this); return null;
},
set: function(value) {
if (this.parent) this.parent.setChildIndex(this, Math.max(0, Math.min(value, this.parent.numChildren-1)));
}
});
Object.defineProperty(obj, 'depth', {
enumerable: true,
get: function() {
return this._depth;
},
set: function(depth) {
this._depth = depth;
if (!zot(this.vrChannel)) {
var parallaxShift = this.vrParallaxDistance ? depth*this.vrParallax*this.vrParallaxDistance : 0;
if (this.vrChannel == "left") {
this.x = this.vrStartX + depth + parallaxShift;
} else if (this.vrChannel == "right") {
this.x = this.vrStartX - depth + parallaxShift;
}
}
}
});
Object.defineProperty(obj, 'blendMode', {
enumerable: true,
get: function() {
return this.compositeOperation;
},
set: function(value) {
this.compositeOperation = value;
}
});
if (!that.name) {
var _name;
Object.defineProperty(that, 'name', {
get: function() {
return _name;
},
set: function(value) {
_name = value;
zim.zimObjectIDs[value] = that;
}
});
}
that._draggable;
Object.defineProperty(that, 'draggable', {
get: function() {
return this._draggable;
},
set: function(value) {
if (value == this._draggable) return;
this._draggable = value;
if (this._draggable) this.drag();
else this.noDrag();
}
});
var frame;
var adCheck;
that.on("mousedown", function (e) {
if (e.target.stage) {
frame = e.target.stage.frame;
if (frame.allowDefault) {
adCheck = true;
frame.allowDefault = false;
}
}
});
that.on("pressup", function (e) {
if (frame && adCheck) frame.allowDefault = true;
});
// EFFECTS
// making 8 properties, 4 that update effect and 4 that do not
// so that regular properties can update effect - obj.hue=20 // updates
// but animate and wiggle can bulk update effect - obj.hueBatch=20 // does not update
var effects = ["hue", "saturation", "brightness", "contrast"];
for (var i=0; i 0 ? this.borderWidth/2 : 0;
a = bounds.x-added;
b = bounds.y-added;
c = bounds.width+added*2;
d = bounds.height+added*2;
}
} else {
c = a;
d = b;
a = 0;
b = 0;
}
}
this.cjsStage_cache(a,b,c,d,scale,options);
return this;
};
this.on("mousedown", function(e) {
var e2 = e.clone();
e2.type = "pressdown";
e.target.dispatchEvent(e2);
}, undefined, false, undefined, true);
this.loop = function(call, reverse, step, start, end) {
return zim.loop(this, call, reverse, step, start, end);
};
this.hitTestGrid = function(width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type) {
return zim.hitTestGrid(this, width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type);
};
this.disposeAllChildren = function() {
for (var i=this.numChildren-1; i>=0; i--) {
var child = this.getChildAt(i)
if (child.dispose) child.dispose();
}
return this;
};
var frame = zdf || 1;
if (createjs && !createjs.stageTransformable && (zdf.retina || typeof exportRoot != "undefined")) {
Object.defineProperty(this, 'scale', {
get: function () {
return this.cjsStage_scale;
},
set: function (value) {
this.cjsStage_scaleX = value;
this.cjsStage_scaleY = value;
zim.scaX = createjs.stageTransformable ? 1 : value;
zim.scaY = createjs.stageTransformable ? 1 : value;
}
});
Object.defineProperty(this, 'scaleX', {
get: function () {
return this.cjsStage_scaleX;
},
set: function (value) {
this.cjsStage_scaleX = value;
zim.scaX = createjs.stageTransformable ? 1 : value;
}
});
Object.defineProperty(this, 'scaleY', {
get: function () {
return this.cjsStage_scaleY;
},
set: function (value) {
this.cjsStage_scaleY = value;
zim.scaY = createjs.stageTransformable ? 1 : value;
}
});
this.localToGlobal = function (x, y) {
return zim.localToGlobal(x, y, this, this.cjsStage_localToGlobal);
};
this.globalToLocal = function (x, y) {
return zim.globalToLocal(x, y, this, this.cjsStage_globalToLocal);
};
this.localToLocal = function (x, y, target) {
return zim.localToLocal(x, y, target, this);
};
}
};
zim.extend(zim.Stage, createjs.Stage, ["cache","localToLocal","localToGlobal","globalToLocal"], "cjsStage", false);
//-50.44
/*--
zim.StageGL = function(canvasID, options)
StageGL
zim class - extends a zim.Stage which extends a createjs.Stage
DESCRIPTION
An extension of a zim.Stage for WebGL support
See ZIM Stage and https://www.createjs.com/docs/easeljs/classes/StageGL.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var stage = new StageGL("canvasID", {preserveBuffer:true, antialias:true});
END EXAMPLE
PARAMETERS
canvasID - (default null) string ID for canvas tag
options - (default null) an object literal with the following properties
FROM https://www.createjs.com/docs/easeljs/classes/StageGL.html
preserveBuffer (default false)
If true, the canvas is NOT auto-cleared by WebGL (the spec discourages setting this to true). This is useful if you want persistent draw effects.
antialias (default false)
Specifies whether or not the browser's WebGL implementation should try to perform anti-aliasing. This will also enable linear pixel sampling on power-of-two textures (smoother images).
transparent (default false)
If true, the canvas is transparent. This is very expensive, and should be used with caution.
premultiply (default false)
Alters color handling. If true, this assumes the shader must account for pre-multiplied alpha. This can help avoid visual halo effects with some assets, but may also cause problems with other assets.
autoPurge (default 1200)
How often the system should automatically dump unused textures with purgeTextures(autoPurge) every autoPurge/2 draws. See purgeTextures for more information.
METHODS
loop(call, reverse, step, start, end) - see the ZIM Display Methods loop() for details
see the ZIM Display Methods loop() for details
hitTestGrid(width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type)
see the ZIM Display Methods hitTestGrid() for details
disposeAllChildren() - remove and dispose all children
See the CreateJS Easel Docs for StageGL methods:
https://www.createjs.com/docs/easeljs/classes/StageGL.html
PROPERTIES
frame - if made with ZIM Frame then frame points to the frame that made the stage
type - holds the class name as a String
width - read only width set by ZIM Frame
height - read only height set by ZIM Frame
See the CreateJS Easel Docs for Stage properties:
https://www.createjs.com/docs/easeljs/classes/StageGL.html
Note: also makes a partial zdf allowing circle.center() to work
but will be overwritten if an actual Frame is made
EVENTS
See the CreateJS Easel Docs for StageGL events, such as:
mouseenter, mouseleave, stagemousedown, stagemousemove, stagemouseup, drawstart, drawend, etc.
and all the Container events such as:
click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+50.45
zim.StageGL = function(canvasID, options) {
z_d("50.45");
if (zot(canvasID)) return;
var tag = canvasID.tagName=="CANVAS"?canvasID:zid(canvasID);
if (zot(tag)) return;
this.cjsStageGL_constructor(canvasID, options);
this.setBounds(0,0,tag.width,tag.height);
this.type = "StageGL";
if (typeof zdf == 'undefined') zdf = {stage:this};
this.cache = function(a,b,c,d,scale,options) {
if (zot(c)) {
if (zot(a)) {
var bounds = this.getBounds();
if (!zot(bounds)) {
var added = this.borderWidth > 0 ? this.borderWidth/2 : 0;
a = bounds.x-added;
b = bounds.y-added;
c = bounds.width+added*2;
d = bounds.height+added*2;
}
} else {
c = a;
d = b;
a = 0;
b = 0;
}
}
this.cjsStageGL_cache(a,b,c,d,scale,options);
return this;
};
this.on("mousedown", function(e) {
var e2 = e.clone();
e2.type = "pressdown";
e.target.dispatchEvent(e2);
}, undefined, false, undefined, true);
this.loop = function(call, reverse, step, start, end) {
return zim.loop(this, call, reverse, step, start, end);
};
this.hitTestGrid = function(width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type) {
return zim.hitTestGrid(this, width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type);
};
this.disposeAllChildren = function() {
for (var i=this.numChildren-1; i>=0; i--) {
var child = this.getChildAt(i)
if (child.dispose) child.dispose();
}
return this;
};
var frame = zdf || 1;
if (createjs && !createjs.stageTransformable && (zdf.retina || typeof exportRoot != "undefined")) {
Object.defineProperty(this, 'scale', {
get: function() {
return this.cjsStage_scale;
},
set: function(value) {
this.cjsStage_scaleX = value;
this.cjsStage_scaleY = value;
zim.scaX = createjs.stageTransformable ? 1 : value;
zim.scaY = createjs.stageTransformable ? 1 : value;
}
});
Object.defineProperty(this, 'scaleX', {
get: function() {
return this.cjsStage_scaleX;
},
set: function(value) {
this.cjsStage_scaleX = value;
zim.scaX = createjs.stageTransformable ? 1 : value;
}
});
Object.defineProperty(this, 'scaleY', {
get: function() {
return this.cjsStage_scaleY;
},
set: function(value) {
this.cjsStage_scaleY = value;
zim.scaY = createjs.stageTransformable ? 1 : value;
}
});
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsStageGL_localToGlobal);
};
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsStageGL_globalToLocal);
};
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
};
}
};
zim.extend(zim.StageGL, createjs.StageGL, ["cache","localToLocal","localToGlobal","globalToLocal"], "cjsStageGL", false);
//-50.45
/*--
zim.Container = function(a, b, c, d, style, group, inherit)
Container
zim class - extends a createjs.Container
DESCRIPTION
A Container object is used to hold other display objects or other containers.
You can then move or scale the container and all objects inside will move or scale.
You can apply an event on a container and use the target property of the event object
to access the object in the container that caused the event
or use the currentTarget property of the event object to access the container itself.
Containers do not have bounds unless some items in the container have bounds -
at which point the bounds are the combination of the bounds of the objects with bounds.
You can manually set the bounds with setBounds(x,y,w,h) - read the CreateJS docs.
Or pass in width and height, or boundsX, boundsY, width, height to have Container set bounds
Manually set bounds will not update automatically unless you setBounds(null).
NOTE: All the ZIM shapes and components extend the Container.
This means all shapes and components inherit the methods and properties below
and indeed, the Container inherits all the createjs.Container methods and properties.
See the CreateJS documentation for x, y, alpha, rotation, on(), addChild(), etc.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var container = new Container();
stage.addChild(container);
container.x = 100; container.y = 100;
// demonstration of adding drag() to a Container
var rect = new Rectangle(100, 100, "blue");
container.addChild(rect); // add rectangle to container
var circle = new Circle(40, "red");
circle.center(container) // add the circle to the container and center
container.drag(); // will drag either the rectangle or the circle
container.drag({currentTarget:true}); // will drag both the rectangle and the circle
// below will reduce the alpha of the object in the container that was clicked (target)
container.on("click" function(e) {e.target.alpha = .5; stage.update();})
// below will reduce the alpha of all the objects in the container (currentTarget)
container.on("click" function(e) {e.currentTarget.alpha = .5; stage.update();})
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
** Container supports three different sets of parameters as follows:
a - (default null) - width and height equal to parameter a (x and y will be 0)
a, b - (default null) - the width and height (x and y will be 0)
a, b, c, d - (default null) - the x, y, width and height of the bounds
if parameter a is not set, then the Container will take bounds that grow with its content
the bounds of the Container can be set at any time with setBounds(a, b, c, d)
if the bounds are set, then the Container bounds will not change as content is added
the bounds can be removed with setBounds(null) and the Container will get auto bounds
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
* This class has all the DISPLAY METHODS introduced in ZIM 4TH
* the methods are available to all ZIM Display objects that extend a ZIM Container
* such as ZIM Rectangle, Circle, Triangle, BLob
* as well as all components like: Label, Button, Slider, Dial, Tab, Pane, etc.
* as well as the ZIM display wrappers: Container, Shape, Sprite, MovieClip and Bitmap
cache(width||x, height||y, null||width, null||height, scale, options, margin) - overrides CreateJS cache() and returns object for chaining
If you do not provide the first four parameters, then the cache dimensions will be set to the bounds of the object
width||x - (default getBounds().x) the width of the chache - or the x if first four parameters are provided
height||y - (default getBounds().y) the height of the chache - or the y if first four parameters are provided
width - (default getBounds().width) the width of the chache - or null if first two parameters are provided
height - (default getBounds().height) the height of the chache - or null if first two parameters are provided
scale - (default 1) set to 2 to cache with twice the fidelity if later scaling up
options - (default null) additional parameters for cache logic - see CreateJS somewhere for details
margin - (default 0) add or subtract a margin from the bounds
eg. margin:10 will make the cache size 10 pixels more on all sides
this can be handy when caching objects with borders - that go half outside the natural bounds
updateCache() - updates the cache if cache() is set
uncache() - uncaches and returns object for chaining
setBounds(width||x||Boundary, height||y, null||width, null||height) - overrides CreateJS setBounds() and returns object for chaining
If you do not provide the any parameters, then the bounds will be reset to the calculated bounds
width||x||Boundary - (default null) the width of the bounds - or the x if four parameters are provided
or a ZIM Boundary Object {x,y,width,height} - same as CreateJS Rectangle - thanks Joseph Diefenbach
height||y - (default width) the height of the bounds - or the y if four parameters are provided
width - (default null) the width of the bounds - or null if only the first two parameters are provided
height - (default null) the height of the bounds - or null if only the first two parameters are provided
childrenToBitmap() - turns content to a Bitmap and adds bitmap to container - removing all other children
specialColor(colorCommand, colorObject) - used internally by ZIM Shapes
to set GradientColor, RadialColor and BitmapColor on a fill or stroke color command
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact) - clones the container, its properties and all its children
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if a Container holds a new Circle(20,[blue,green])
then its clone might be blue or green
If exact is set to true then the clone will be whatever color was picked for the original circle
disposeAllChildren() - removes and disposes all children but leaves the container (see also CreateJS removeAllChildren() which does not dispose them)
dispose(disposing) - removes from parent, removes event listeners - must still set outside references to null for garbage collection
if calling dispose() on the super class from a custom class then pass in true to indicate already started dispose (otherwise infinite loops)
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
** common to all DisplayObjects that extend a Container such as ZIM Shapes and Components
type - holds the class name as a String
group - used when the object is made to add STYLE with the group selector (like a CSS class)
** bounds must be set first (or width and height parameters set) for these to work
** setting these adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
draggable - set to true for a default drag() and false for a noDrag()
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
effects - an object that holds effects added such as blur, glow, shadow, color, multi and alpha - see effect() under ZIM Methods
** the following are convenience Effects that run a ZIM MultiEffect()
** these can use a lot of processing when animating - see Docs for effects()
** batch versions are available too as hueBatch, etc. these will not update the effect until updateEffects() is called on the object
hue - the tint of an object between -180 and 180 with 0 being no change
saturation - the amount of color of an object between -100 and 100 with 0 being no change
brightness - the lightness or darkness of an object between -255 and 255 with 0 being no change
contrast - the crispness of an object between -100 and 100 with 0 being no change
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scale, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+50.5
zim.Container = function(a, b, c, d, style, group, inherit) {
var sig = "a, b, c, d, style, group, inherit";
var duo; if (duo = zob(zim.Container, arguments, sig, this)) return duo;
if (!zim.containerCheck) {
z_d("50.5");
z_d("50.435"); // global dispose too - may not catch dispose in DISTILL check
zim.containerCheck=true;
}
this.cjsContainer_constructor();
this.type = "Container";
this.group = group;
var that = this;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(a)) a = DS.a!=null?DS.a:null;
if (zot(b)) b = DS.b!=null?DS.b:null;
if (zot(c)) c = DS.c!=null?DS.c:null;
if (zot(d)) d = DS.d!=null?DS.d:null;
var n = normalizeBounds(a, b, c, d);
function normalizeBounds(a, b, c, d) {
var bounds = [];
if (zot(a)) {
bounds = [a,b,c,d];
} else if (zot(b)) {
bounds = [a.x, a.y, a.width, a.height];
} else if (!zot(c)) {
bounds[0] = a;
bounds[1] = b;
bounds[2] = c;
bounds[3] = d;
} else {
bounds[0] = 0;
bounds[1] = 0;
bounds[2] = a;
bounds[3] = b;
}
if (zot(bounds[3])) bounds[3] = bounds[2];
return bounds;
}
if (!zot(a)) this.setBounds(n[0],n[1],n[2],n[3]); // es6 to fix
this.cache = function(a,b,c,d,scale,options,margin) {
if (this.type=="AC"&&zdf) {zdf.ac("cache", arguments, this); return this;}
var sig = "a,b,c,d,scale,options,margin";
var duo; if (duo = zob(that.cache, arguments, sig)) return duo;
var bounds = that.getBounds();
if (zot(c)) {
if (zot(a)) {
if (!zot(bounds)) {
var added = that.borderWidth > 0 ? that.borderWidth/2 : 0;
a = bounds.x-added;
b = bounds.y-added;
c = bounds.width+added*2;
d = bounds.height+added*2;
}
} else {
c = a;
d = b;
a = 0;
b = 0;
}
}
if (that.type == "Triangle") {
a-=that.borderWidth?that.borderWidth:0;
c+=that.borderWidth?that.borderWidth*2:0;
b-=that.borderWidth?that.borderWidth:0;
d+=that.borderWidth?that.borderWidth*2:0;
}
if (zot(margin)) margin = 0;
that.cjsContainer_cache(a-margin,b-margin,c+margin*2,d+margin*2,scale,options);
if (bounds) that.setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
return that;
};
this.uncache = function() {
that.cjsContainer_uncache();
return that;
};
this.childrenToBitmap = function () {
var cached = this.cacheCanvas;
var pic = new zim.Bitmap(this.cache().cacheCanvas);
if (!cached) this.uncache();
this.removeAllChildren();
pic.addTo(this);
return this;
};
var frame = zdf || 1;
if (createjs && !createjs.stageTransformable && frame.retina) {
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsContainer_localToGlobal);
};
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsContainer_globalToLocal);
};
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
};
}
this.setBounds = function(a,b,c,d) {
var n = normalizeBounds(a, b, c, d);
this.cjsContainer_setBounds(n[0],n[1],n[2],n[3]);
return this;
};
this.disposeAllChildren = function() {
for (var i=this.numChildren-1; i>=0; i--) {
var child = this.getChildAt(i)
if (child.dispose) child.dispose();
}
return this;
};
zim.displayBase(that);
if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function(exact) {
if (this.type=="AC"&&zdf) {
if (zon) {zogy("ZIM asset() - cannot clone lazy loaded asset - use Frame() assets parameter or loadAssets() method")};
zdf.ac("clone", arguments, this);
return this;
}
var currentBounds = this.getBounds();
if (zot(currentBounds)) currentBounds = {x:null, y:null, width:null, height:null};
return this.cloneChildren(this.cloneProps(new zim.Container(currentBounds.x,currentBounds.y,currentBounds.width,currentBounds.height, style, this.group, inherit)), exact);
};
this.hasProp = function(prop) {
return (!zot(this[prop]) || this.hasOwnProperty(prop));
};
};
zim.Container.prototype.dispose = function(disposing) {
recursiveDispose(this, disposing);
return true;
};
zim.Container.prototype.specialColor = function(command, co) {
if (co.type=="GradientColor") command.linearGradient(co.colors, co.ratios, co.x0, co.y0, co.x1, co.y1);
else if (co.type=="RadialColor") command.radialGradient(co.colors, co.ratios, co.x0, co.y0, co.r0, co.x1, co.y1, co.r1);
else if (co.type == "BitmapColor") command.bitmap(co.image, co.repetition, co.matrix);
};
function recursiveDispose(obj, disposing) {
// zogr(obj.type)
if (obj) zim.gD(obj); // globalDispose function for common elements
// dispose was fixed in ZIM 10.7.0 in TWO ways:
// ONE
// Some classes have custom dispose - so may want to call these.
// If disposing is true then we are coming from a custom dispose already
// otherwise, call the custom dispose and pass true to say we are already disposing containers
// otherwise the custom dispose will try and call the container dispose and we have an endless loop
if (!disposing && obj && obj.dispose && obj.dispose !== zim.Container.prototype.dispose) {
obj.dispose(null,null,true);
}
// TWO
// dispose was only disposing type=="CONTAINER"
// so should have been type=="Container" - but even that is too narrow
// as would not include components parts or Tile parts, etc.
// so fixed it to include all decendents of Container by testing for addChild
// zog(obj.type)
// if (obj.type == "Container") {
if (obj && obj.addChild) {
obj.dispatchEvent("removed");
obj.removeAllEventListeners();
if (obj.numChildren) {
for (var i=obj.numChildren-1; i>=0; i--) {
recursiveDispose(obj.getChildAt(i));
}
}
}
if (obj && obj.parent) obj.parent.removeChild(obj);
}
zimify(zim.Container.prototype);
zim.extend(zim.Container, createjs.Container, ["cache","uncache","setBounds","clone","localToLocal","localToGlobal","globalToLocal"], "cjsContainer", false);
//-50.5
/*--
zim.Shape = function(a, b, c, d, graphics, optimize, style, group, inherit)
Shape
zim class - extends a createjs.Shape
DESCRIPTION
ZIM Shape lets you draw dynamic shapes beyond the ZIM provided shapes.
You make a new shape object and then draw in its graphics property
using similar commands to the HTML Canvas commands (and Flash Bitmap drawing).
See the CreateJS Easel Shapes and Graphics docs:
http://www.createjs.com/docs/easeljs/classes/Graphics.html
ALSO SEE: https://zimjs.com/docs.html?item=Generator for dynamically drawing into shapes like Processing (P5js)
ALSO SEE: https://zimjs.com/docs.html?item=Squiggle,Blob for odd shapes and user adjustable shapes
ALSO SEE: https://zimjs.com/docs.html?item=Pen for dynamic drawing of lines
ALSO SEE: https://zimjs.com/docs.html?item=Connectors for dynamic connections
// these mean we rarely use Shape directly but all of above were made in ZIM with Shape
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
NOTE: as of ZIM 10.6.0 the tiny API is available right on the Shape (no need for graphics)
EXAMPLE
// NEWER CODE
// Uses the tiny API (see options down below) right on the ZIM Shape
// for example: f() is fill() and dr() is drawRect()
// s() is beginStroke(), ss() is setStrokeStyle(), mt() is moveTo(), lt() is lineTo()
// draw a red rectangle into a shape
new Shape().f(red).dr(0,0,200,100).addTo();
// but it would be easier to use
// new Rectangle(200, 100, red).addTo();
// we can draw lines, etc. (but also see the ZIM Line object)
new Shape().s(blue).ss(5).mt(200,200).lt(300,300).addTo();
// note - we can draw as much as we want in the same shape
END EXAMPLE
EXAMPLE
// OLDER CODE
// The first example uses a tiny API (see options below)
// The traditional full commands are available on the graphics object:
var shape = new Shape().addTo();
shape.graphics.beginFill(red).drawRect(0,0,200,100);
// or often we stored the graphics object in a variable g
var g = shape.graphics;
g.beginStroke(blue).moveTo(200,200).lineTo(300,300);
END EXAMPLE
EXAMPLE
// to change a color or stroke after it has been made use command:
var shape = new Shape().addTo();
var strokeColor = shape.s(red).command;
shape.dr(50,50,100,100);
stage.update();
timeout(1, function(){
strokeColor.style = blue;
stage.update();
});
// This seems a little complex which is why ZIM provides many basic shapes
// Rectangle, Circle, Triangle, Squiggle, Blob, Poly, Line, Flare
// that can be adjusted dynamically with properties
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
** Shape supports three different sets of parameters as follows:
a - (default null) - width and height equal to parameter a (x and y will be 0)
a, b - (default null) - the width and height (x and y will be 0)
a, b, c, d - (default null) - the x, y, width and height of the bounds
graphics - (default null) a CreateJS Graphics instance (see CreateJS docs)
or just use the graphics property of the shape object (like usual)
optimize - (default false) set to true to not store graphics methods directly on Shape
this means the shapes graphics property will need to be used to access f(), s(), ss(), etc.
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
The following shortcuts to CreateJS graphics methods are provided (as long as optimize is false)
See https://www.createjs.com/docs/easeljs/classes/Graphics.html for definitions and parameters
mt() moveTo
lt() lineTo
a() arc
at() arcTo
bt() bezierCurveTo
ct() curveTo
qt() quadraticCurveTo (same as curveTo)
r() rect
cp() closePath
c() clear
f() beginFill
lf() beginLinearGradientFill
rf() beginRadialGradientFill
bf() beginBitmapFill
ef() endFill
ss() setStrokeStyle
sd() setStrokeDash
s() beginStroke
ls() beginLinearGradientStroke
rs() beginRadialGradientStroke
bs() beginBitmapStroke
es() endStroke
dr() drawRect
rr() drawRoundRect
rc() drawRoundRectComplex
dc() drawCircle
de() drawEllipse
dp() drawPolyStar
pg() polygon // added in ZIM CreateJS 1.3.3 (Diamond)
p() decodePath
cache(width||x, height||y, null||width, null||height, scale, options, margin) - overrides CreateJS cache() and returns object for chaining
If you do not provide the first four parameters, then the cache dimensions will be set to the bounds of the object
width||x - (default getBounds().x) the width of the chache - or the x if first four parameters are provided
height||y - (default getBounds().y) the height of the chache - or the y if first four parameters are provided
width - (default getBounds().width) the width of the chache - or null if first two parameters are provided
height - (default getBounds().height) the height of the chache - or null if first two parameters are provided
scale - (default 1) set to 2 to cache with twice the fidelity if later scaling up
options - (default null) additional parameters for cache logic - see CreateJS somewhere for details
margin - (default 0) add or subtract a margin from the bounds
eg. margin:10 will make the cache size 10 pixels more on all sides
this can be handy when caching objects with borders - that go half outside the natural bounds
setBounds(width||x, height||y, null||width, null||height) - overrides CreateJS setBounds() and returns object for chaining
width||x - (default null) the width of the bounds - or the x if four parameters are provided
height||y - (default width) the height of the bounds - or the y if four parameters are provided
width - (default null) the width of the bounds - or null if only the first two parameters are provided
height - (default null) the height of the bounds - or null if only the first two parameters are provided
hasProp(property) - returns true if String property exists on object else returns false
clone(recursive) - makes a copy of the shape
recursive defaults to true so copy will have own copy of graphics
set recursive to false to have clone share graphic property
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), placeReg(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
command - save a previously chained operation as a command
then can use the command to change the operation later (see example above)
group - used when the object is made to add STYLE with the group selector (like a CSS class)
** bounds must be set first (or width and height parameters set) for these to work
** setting these adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
draggable - set to true for a default drag() and false for a noDrag()
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
effects - an object that holds effects added such as blur, glow, shadow, color, multi and alpha - see effect() under ZIM Methods
** the following are convenience Effects that run a ZIM MultiEffect()
** these can use a lot of processing when animating - see Docs for effects()
** batch versions are available too as hueBatch, etc. these will not update the effect until updateEffects() is called on the object
hue - the tint of an object between -180 and 180 with 0 being no change
saturation - the amount of color of an object between -100 and 100 with 0 being no change
brightness - the lightness or darkness of an object between -255 and 255 with 0 being no change
contrast - the crispness of an object between -100 and 100 with 0 being no change
ALSO: see the CreateJS Easel Docs for Shape properties, such as:
graphics, x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseEnabled, etc.
EVENTS
See the CreateJS Easel Docs for Shape events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+50.6
zim.Shape = function(a, b, c, d, graphics, optimize, style, group, inherit) {
var sig = "a, b, c, d, graphics, optimize, style, group, inherit";
var duo; if (duo = zob(zim.Shape, arguments, sig, this)) return duo;
z_d("50.6");
this.cjsShape_constructor(graphics);
this.type = "Shape";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
var that = this;
if (zot(a)) a = DS.a!=null?DS.a:null;
if (zot(b)) b = DS.b!=null?DS.b:null;
if (zot(c)) c = DS.c!=null?DS.c:null;
if (zot(d)) d = DS.d!=null?DS.d:null;
if (zot(graphics)) graphics = DS.graphics!=null?DS.graphics:null;
if (zot(optimize)) optimize = DS.optimize!=null?DS.optimize:false;
var n = normalizeBounds(a, b, c, d);
function normalizeBounds(a, b, c, d) {
var bounds = [];
if (!zot(c)) {
bounds[0] = a;
bounds[2] = c;
bounds[1] = b;
bounds[3] = d;
} else {
bounds[0] = 0;
bounds[2] = a;
bounds[1] = 0;
bounds[3] = b;
}
if (zot(bounds[3])) bounds[3] = bounds[2];
return bounds;
}
if (!zot(a)) this.setBounds(n[0],n[1],n[2],n[3]); // es6 to fix
if (!optimize) {
var shorts = ["mt","lt","a","at","bt","ct","qt","cp","c",
"f","lf","rf","bf","ef","ss","sd","s",
"ls","rs","bs","es","dr","rr","rc","dc","de","dp","pg","p"];
for (var i=0; i 0 ? that.borderWidth/2 : 0;
a = bounds.x-added;
b = bounds.y-added;
c = bounds.width+added*2;
d = bounds.height+added*2;
}
} else {
c = a;
d = b;
a = 0;
b = 0;
}
}
if (zot(margin)) margin = 0;
that.cjsShape_cache(a-margin,b-margin,c+margin*2,d+margin*2,scale,options);
return that;
};
this.setBounds = function(a,b,c,d) {
var n = normalizeBounds(a, b, c, d);
this.cjsShape_setBounds(n[0],n[1],n[2],n[3]);
return this;
};
if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function(recursive) {
if (zot(recursive)) recursive = true;
var currentBounds = this.getBounds();
if (zot(currentBounds)) currentBounds = {x:null, y:null, width:null, height:null};
var c = that.cloneProps(new zim.Shape(currentBounds.x,currentBounds.y,currentBounds.width,currentBounds.height, graphics, style, group, inherit));
if (recursive) c.graphics = that.graphics.clone();
else c.graphics = that.graphics;
return c;
};
var frame = zdf || 1;
if (createjs && !createjs.stageTransformable && frame.retina) {
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsShape_localToGlobal);
};
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsShape_globalToLocal);
};
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
};
}
this.hasProp = function(prop) {
return (!zot(this[prop]) || this.hasOwnProperty(prop));
};
// this.pg = function(points, close) {
// if (!Array.isArray(points)) points = Array.from(arguments);
// var type = points[0].x != null?"obj":points[0][0] != null?"arr":"par";
//
// var p, fp, sp;
// if (type=="obj") p = points[0];
// else if (type=="arr") p = {x:points[0][0], y:points[0][1]||0};
// else p = {x:points[0], y:points[1]||0};
// fp = {x:p.x, y:p.y};
// this.mt(fp.x, fp.y);
// for (var i=1; i 0 ? this.borderWidth/2 : 0;
a = bounds.x-added;
b = bounds.y-added;
c = bounds.width+added*2;
d = bounds.height+added*2;
}
} else {
c = a;
d = b;
a = 0;
b = 0;
}
}
var bounds = this.getBounds();
this.cjsBitmap_cache(a,b,c,d,scale,options);
this.setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
return this;
};
this.clone = function() {
var c = this.cloneProps(new zim.Bitmap(image, width, height, left, top, that.fileID, style, this.group, inherit));
c.cloned = true;
return c;
};
var frame = zdf || 1;
if (createjs && !createjs.stageTransformable && frame.retina) {
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsBitmap_localToGlobal);
};
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsBitmap_globalToLocal);
};
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
};
}
this.hasProp = function(prop) {
return (!zot(this[prop]) || this.hasOwnProperty(prop));
};
var myContext;
this.getColorAt = function(x,y) {
if (!myContext) {
that.cache();
myContext = that.cacheCanvas.getContext('2d');
that.uncache();
}
var d = myContext.getImageData(x, y, 1, 1).data;
return "rgba("+d[0]+","+d[1]+","+d[2]+","+d[3]+")";
};
zim.displayBase(that);
if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.dispose = function(a,b,disposing) {
zim.gD(this); // globalDispose function for common elements
this.dispatchEvent("removed");
this.removeAllEventListeners();
if (!this.cloned) {
if (this.id) {
if (this.stage && this.stage.frame) frame = this.stage.frame;
else frame = zdf;
if (frame && frame.assets) {
if (frame.assets[this.id]) delete frame.assets[this.id];
}
if (zim.assets[this.id]) delete zim.assets[this.id];
}
}
if (this.parent) this.parent.removeChild(this);
};
};
zim.Bitmap.fromData = function(data, callback) {
var width = 100;
var height = 100;
var img = new Image();
img.onload = function() {
width = img.naturalWidth;
height = img.naturalHeight;
if (zot(width)) width = img.width;
if (zot(height)) height = img.height;
var bitmap = new zim.Bitmap(data, width, height);
setTimeout(function() {
callback(bitmap);
}, 50);
}
img.src = data;
};
zim.extend(zim.Bitmap, createjs.Bitmap, ["cache","clone","dispose","localToLocal","localToGlobal","globalToLocal"], "cjsBitmap", false);
zimify(zim.Bitmap.prototype);
//-50.7
/*--
zim.Sprite = function(image, cols, rows, count, offsetX, offsetY, spacingX, spacingY, width, height, animations, json, id, globalControl, spriteSheet, label, frame, style, group, inherit)
Sprite
zim class - extends a createjs.Sprite
DESCRIPTION
A Sprite plays an animation of a spritesheet
which is a set of images layed out in one file.
You play the Sprite with the run() method.
This animates the Sprite over a given time
with various features like playing a labelled animation,
playing animation series, wait, loop, rewind and call functions.
This actually runs a ZIM animation and animates the frames.
SEE:
https://zimjs.com/spritesheet/
https://zimjs.com/spritesheet/skateboard.html
https://codepen.io/danzen/pen/yEKbbR
https://codepen.io/danzen/pen/VdXzLV
https://zimjs.com/zide/
https://zimjs.com/explore/sidescroller.html (with keyboard)
NOTE: A ZIM Sprite handles both an evenly tiled spritesheet - use cols and rows
and an un-evenly tiled spritesheet - use the json parameter.
The json can come from TexturePacker for instance exported for EaselJS/CreateJS
CreateJS Easel Sprite and SpriteSheet docs:
http://www.createjs.com/docs/easeljs/classes/Sprite.html
http://www.createjs.com/docs/easeljs/classes/SpriteSheet.html
You can optionally pass in an existing createjs.SpriteSheet as a parameter.
When you do so, all other parameters are ignored.
NOTE: You can use CreateJS gotoAndPlay(), play(), etc.
but we found the framerate could not be kept
with other animations or Ticker events running.
So we recommend using the ZIM Sprite run() method.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// inside Frame template
// boom.png is a sprite sheet found online
// It has 8 columns and 6 rows that we can visually count
// We can enter a total parameter if it does not end evenly in the grid
// A graphics editor (like Photoshop) could be used to see
// if there is an offset or spacing, etc. and enter those as parameters
// In this case, we do not need to do any of this - just enter the cols and rows
frame.on("complete", function() {
var spriteImage = frame.asset("boom.png");
var animation = new Sprite({
image:spriteImage,
cols:8,
rows:6,
animations:{mid:[10,20], end:[30,40]} // optional animations with labels
// see CreateJS SpriteSheet docs for the various animation format as there are a few different ones!
});
animation.center();
animation.run(2); // plays the frames of the Sprite over 2 seconds (master time)
// OR use the label to play the frames listed in animations parameter
animation.run(1, "mid");
// OR run a series of animations
// by passing an array of label objects to the label parameter
// these each have a time so the master time is ignored
// they can also have any of the run() parameters
// if you provide an array of labels, you cannot rewind the overall animation
animation.run(null, [
{label:"mid", time:1},
{label:"end", time:.5, loop:true, loopCount:5, call:function(){zog("loops done");}},
{startFrame:10, endFrame:20, time:1}
]);
// OR can call a function when done
animation.run(1, "mid", function(){
stage.removeChild(animation);
stage.update();
});
// OR can loop the animation
animation.run({time:2, loop:true}); // see run() parameters for more
});
END EXAMPLE
EXAMPLE
// using Sprite as a texture atlas - or spritesheet of different images
// see: https://zimjs.com/explore/fruit.html
// load in assets and path
var frame = new Frame({assets:["fruit.png", "fruit.json"], path:"assets/"});
frame.on("ready", function() {
new Sprite({json:frame.asset("fruit.json"), label:"apple"}).center();
frame.stage.update();
});
END EXAMPLE
EXAMPLE
// Here is an example with CreateJS SpriteSheet data
// robot.png is a sprite sheet made by ZOE based on a Flash swf
// you can also make your own with Photoshop or Texture Packer
frame.loadAssets("robot.png");
frame.on("complete", function() {
// using ZOE to export swf animation to spritesheet data
// spritesheet data uses the image name, not the Bitmap itself
var image = frame.asset("robot.png").image;
var spriteData = {
"framerate":24,
"images":[image],
"frames":[[0, 0, 256, 256, 0, -54, -10], many more - etc.],
"animations":{}
};
var animation = new Sprite({json:spriteData});
animation.center();
animation.run(2); // note, duration alternative to framerate
});
OR
// load in data from external JSON
frame.loadAssets(["robot.json", "robot.png"]);
// ... same as before
var animation = new Sprite({json:frame.asset("robot.json")});
// ... same as before
// see CreateJS SpriteSheet docs for the format of the JSON file
// including various animation formats
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
image - the ZIM Bitmap for the spritesheet
cols - (default 1) - the columns in the spritesheet
rows - (default 1) the rows in the spritesheet
count - (default cols*rows) how many total frames in the spritesheet
offsetX - (default 0) the pixels from the left edge to the frames
offsetY - (default 0) the pixels from the top edge to the frames
spacingX - (default 0) the horizontal spacing between the frames
spacingY - (default 0) the vertical spacing between the frames
width - (default image width) the width including offset and spacing for frames
height - (default image height) the height including offset and spacing for frames
animations - (default null) an object literal of labels holding frames to play
{label:3, another:[4,10]}
run(1, "label") would play frame 3 for a second
run(1, "another") would play frames 4 to 10 for a second
{unordered:{frames:[1,2,3,22,23,24,"anotherLabel",5,6], next:prevLabel}}
There are also ways to set speeds - but would recommend dividing into simple labels
and using the label series technique available with the run() method
json - (default null) a JSON string for a CreateJS SpriteSheet
If you pass in a json parameter, all other parameters are ignored
NOTE: remember that JSON needs quotes around the animation properties above:
{"label":3, "another":[4,10]}
id - (default randomly assigned) an id you can use in other animations - available as sprite.id
use this id in other animations for pauseRun and stopRun to act on these as well
globalControl - (default true) pauseRun and stopRun will control other animations with same id
spriteSheet - (default null) pass in a CreateJS SpriteSheet to build a Sprite from that
label - (default null) pass in a label to stop on initially - to play from a label use the run({label:val}) method
frame - (default zimDefaultFrame) specify a Frame other than the default frame
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
run(time, label, call, params, wait, waitedCall, waitedParams, loop, loopCount, loopWait, loopCall, loopParams, loopWaitCall, loopWaitParams, loopPick, rewind, rewindWait, rewindCall, rewindParams, rewindWaitCall, rewindWaitParams, rewindTime, rewindEase, startFrame, endFrame, tweek, id, globalControl)
The run() method animates the Sprite over an amount of time
Would recommend this method over the CreateJS play() and gotoAndPlay()
methods because the framerate for these get overwritten by other stage.update() calls
With run() you get other nice ZIM animate features as well as follows:
Returns the object for chaining
Can be paused with pauseAnimate(true) or unpaused with pauseAnimate(false)
Can be stopped with stopAnimate() on the Sprite
supports DUO - parameters or single object with properties below
time (default 1) - the time in seconds to run the animations (the master time)
label (default null) - a label specified in the Sprite animations parameter
if this is an array holding label objects for example:
[{label:"run", time:1}, {label:"stand", time:2}]
then the sprite will play the series with the times given and ignore the master time
Note: if any of the series has a loop and loops forever (a loopCount of 0 or no loopCount)
then this will be the last of the series to run
rewind is not available on the outside series but is available on an inside series
call - (default null) the function to call when the animation is done
params - (default target) a single parameter for the call function (eg. use object literal or array)
wait - (default 0) seconds to wait before doing animation
waitedCall - (default null) call the function after a wait time if there is one
waitedParams - (default null) parameters to pass to the waitedCall function
loop - (default false) set to true to loop animation
loopCount - (default 0) if loop is true how many times it will loop (0 is forever)
loopWait - (default 0) seconds to wait before looping (post animation wait)
loopCall - (default null) calls function after loop and loopWait (not including last loop)
loopParams - (default target) parameters to send loopCall function
loopWaitCall - (default null) calls function after at the start of loopWait
loopWaitParams - (default target) parameters to send loopWaitCall function
rewind - (default false) set to true to rewind (reverse) animation (doubles animation time) (not available on label series)
rewindWait (default 0) seconds to wait in the middle of the rewind
rewindCall (default null) calls function at middle of rewind after rewindWait
rewindParams - (default target) parameters to send rewindCall function
rewindWaitCall (default null) calls function at middle of rewind before rewindWait
rewindWaitParams - (default target) parameters to send rewindCall function
rewindTime - (default time) set to a time in seconds to adjust the time to rewind
rewindEase - (default null) see ease parameter for options for rewind ease
note - this goes backwards - so "bounceOut" would happen at the end of the rewind
startFrame - (default null - or 0) the frame to start on - will be overridden by a label with frames
endFrame - (default null - or totalFrames) the frame to end on - will be overridden by a label with frames
tweek - (default 1) a factor for extra time on rewind and loops if needed
id - (default randomly assigned) an id you can use in other animations - available as sprite.id
use this id in other animations for pauseRun and stopRun to act on these as well
globalControl - (default true) pauseRun and stopRun will control other animations with same id
pauseOnBlur - (default true) pause the sprite when the window is not seen or set to false to keep playing the sprite
pauseRun(state) - pause or unpause the animation (including an animation series)
state - (default true) when true the animation is paused - set to false to unpause
returns object for chaining
stopRun() - stop the sprite from animating
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Sprite methods, such as:
play(), gotoAndPlay(), gotoAndStop(), stop(), advance(),
on(), off(), getBounds(), setBounds(), dispatchEvent(), etc.
PROPERTIES
type - holds the class name as a String
id - an id that you can use in other animations to also be controlled by pauseRun() and stopRun()
frame - get and set the current frame of the Sprite
normalizedFrame - if animations have CreateJS speeds applied, zim handles these by making extra frames
for example, if a speed is given of .5 then two frames are made (min resulution is .1)
normalizedFrames - an array of total frames after being normalized - really for internal usage
totalFrames - get the total frames of the Sprite - read only
animations - the animations data with labels of frames to animate
running - is the sprite animation being run (includes both paused and unpaused) - read only
runPaused - is the sprite animation paused (also returns paused if not running) - read only
note: this only syncs to pauseRun() and stopRun() not pauseAnimate() and stopAnimate()
note: CreateJS has paused, etc. but use that only if running the CreateJS methods
such as gotoAndPlay(), gotoAndStop(), play(), stop()
draggable - set to true for a default drag() and false for a noDrag()
group - used when the object is made to add STYLE with the group selector (like a CSS class)
** bounds must be set first (or width and height parameters set) for these to work
** setting these adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
draggable - set to true for a default drag() and false for a noDrag()
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
effects - an object that holds effects added such as blur, glow, shadow, color, multi and alpha - see effect() under ZIM Methods
** the following are convenience Effects that run a ZIM MultiEffect()
** these can use a lot of processing when animating - see Docs for effects()
** batch versions are available too as hueBatch, etc. these will not update the effect until updateEffects() is called on the object
hue - the tint of an object between -180 and 180 with 0 being no change
saturation - the amount of color of an object between -100 and 100 with 0 being no change
brightness - the lightness or darkness of an object between -255 and 255 with 0 being no change
contrast - the crispness of an object between -100 and 100 with 0 being no change
ALSO: see the CreateJS Easel Docs for Sprite properties, such as:
currentFrame, framerate, paused, currentAnimation, currentAnimationFrame, spriteSheet,
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseEnabled, etc.
EVENTS
See the CreateJS Easel Docs for Sprite events, such as:
animationend, change, added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+50.8
zim.Sprite = function(image, cols, rows, count, offsetX, offsetY, spacingX, spacingY, width, height, animations, json, id, globalControl, spriteSheet, label, frame, style, group, inherit) {
var sig = "image, cols, rows, count, offsetX, offsetY, spacingX, spacingY, width, height, animations, json, id, globalControl, spriteSheet, label, frame, style, group, inherit";
var duo; if (duo = zob(zim.Sprite, arguments, sig, this)) return duo;
z_d("50.8");
this.type = "Sprite";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
var that = this;
var sheet;
if (zot(frame)) frame = DS.frame!=null?DS.frame:zdf;
if (zot(json) && !zot(image)) {
if (zot(cols)) cols = DS.cols!=null?DS.cols:1;
if (zot(rows)) rows = DS.rows!=null?DS.rows:1;
if (zot(count)) count = DS.count!=null?DS.count:(cols*rows);
if (zot(offsetX)) offsetX = DS.offsetX!=null?DS.offsetX:0;
if (zot(offsetY)) offsetY = DS.offsetY!=null?DS.offsetY:0;
if (zot(spacingX)) spacingX = DS.spacingX!=null?DS.spacingX:0;
if (zot(spacingY)) spacingY = DS.spacingY!=null?DS.spacingY:0;
if (zot(width)) width = DS.width!=null?DS.width:image.width;
if (zot(height)) height = DS.height!=null?DS.height:image.height;
var frameW = (width-offsetX+spacingX) / cols - spacingX;
var frameH = (height-offsetY+spacingY) / rows - spacingY;
var frames = [];
var num = 0;
outer:
for (var j=0; j count) break outer;
frames.push([
offsetX + i*(frameW+spacingX),
offsetY + j*(frameH+spacingY),
frameW,
frameH
]);
}
}
makeSheet(image, frames, animations);
} else if (spriteSheet) {
sheet = spriteSheet;
animations = sheet.animations;
} else if (json) {
// even though data is in JSON, may want to create SpriteSheet from image
// so that cors will work - so see if provided an image
// or that the images in the JSON are available in frame.assets
frames = json.frames;
animations = json.animations;
if (!zot(image)) {
makeSheet(image, frames, animations);
} else {
var im = json.images?json.images[0]:null;
if (!im || !im.split) {
sheet = new createjs.SpriteSheet(json);
} else {
var assets = [];
zim.loop(json.images, function(im) {
var imEnd = im.split("/").pop();
if (frame.asset(im) && frame.asset(im).type != "EmptyAsset") {
assets.push(frame.asset(im));
} else if (frame.asset(imEnd) && frame.asset(imEnd).type != "EmptyAsset") {
assets.push(frame.asset(imEnd));
} else if (frame.asset(im).type != "EmptyAsset") {
assets.push(frame.asset(im));
} else {
if (zon) zogy("Sprite() - please preload Sprite in Frame or with loadAssets");
}
});
makeSheet(assets, frames, animations);
}
}
} else {
return;
}
function makeSheet(image, frames, animations) {
if (!Array.isArray(image)) image = [image];
zim.loop(image, function(im, i) {
image[i] = im.image;
});
var spriteData = {
images:image,
frames:frames,
animations:animations?animations:[]
};
sheet = new createjs.SpriteSheet(spriteData);
}
this.animations = animations;
this.cjsSprite_constructor(sheet, label);
if (!zot(label)) this.stop();
if (zot(id)) id = zim.makeID();
this.id = id;
if (zot(globalControl)) globalControl = true;
that.globalControl = globalControl;
var _normalizedFrame = 0;
var _normalizedFrames;
this.parseFrames = function(label, startFrame, endFrame, fromDynamo) {
var frames = [];
var minSpeed = Number.MAX_VALUE;
var maxSpeed = 0;
if (zot(label)) {
if (zot(startFrame)) startFrame = 0;
if (zot(endFrame)) endFrame = that.totalFrames-1;
addSequential(startFrame, endFrame);
} else {
if (zot(that.animations) || zot(that.animations[label])) return [];
var a = that.animations[label];
processAnimation(a);
}
function processAnimation(a) {
if (Array.isArray(a)) {
processArray(a);
} else if (a.constructor == {}.constructor) {
processObject(a);
} else if (!isNaN(a)) {
frames.push({f:Math.floor(a), s:1});
}
}
function processArray(a) {
addSequential(a[0], a[1], a[3]);
if (a[2] && !zot(that.animations[a[2]])) processAnimation(that.animations[a[2]]);
}
function processObject(a) {
if (zot(a.frames)) return;
if (zot(a.speed)) a.speed = 1;
for (var i=0; i maxSpeed) maxSpeed = a.speed;
frames.push({f:a.frames[i], s:a.speed});
}
if (a.next && !zot(that.animations[a.next])) processAnimation(that.animations[a.next]);
}
function addSequential(start, end, speed) {
if (zot(speed)) speed = 1;
if (end > start) {
for (var i=start; i<=end; i++) {inner(i);}
} else {
for (var i=end; i<=start; i++) {inner(start-(i-end));}
}
function inner(i) {
if (speed < minSpeed) minSpeed = speed;
if (speed > maxSpeed) maxSpeed = speed;
frames.push({f:i, s:speed});
}
}
if (fromDynamo) return frames;
// run() uses an array of frame numbers (normalized to speed) where dynamo uses the speed
// normalize up to 1/10 - as in if put at .1 then have to multiply all others speeds by 10
minSpeed = zim.constrain(zim.decimals(minSpeed), .1);
maxSpeed = zim.constrain(zim.decimals(maxSpeed), .1);
// normalize speed:
var framesNormalized = [];
var normalize = (minSpeed != maxSpeed);
var fr;
for (var i=0; i 0) extraTime = tt / (endFrame-startFrame) / 2; // slight cludge - seems to look better?
// if (i==0) firstStartFrame = startFrame;
}
//startFrame = firstStartFrame;
if (obj.length == 0) return this;
if (obj.length == 1) { // just one label in list ;-)
time = obj[0].time;
label = lastLabel;
setSingle();
} else {
that.gotoAndStop(firstStartFrame);
}
} else { // single label
setSingle();
}
function setSingle() {
_normalizedFrames = that.parseFrames(label, startFrame, endFrame);
_normalizedFrame = 0;
that.gotoAndStop(_normalizedFrames[_normalizedFrame]);
startFrame = endFrame = null;
obj = {normalizedFrame:_normalizedFrames.length-1};
}
if (zot(time)) time = timeType=="s"?1:1000;
// if already running the sprite then stop the last run
if (that.running) that.stopAnimate(that.id);
that.running = true;
if (!Array.isArray(obj)) {
var extraTime = 0;
if (endFrame-startFrame > 0) extraTime = time / Math.abs(endFrame-startFrame) / 2; // slight cludge - seems to look better?
if (_normalizedFrames && _normalizedFrames.length>0) extraTime = time / _normalizedFrames.length / 2; // slight cludge - seems to look better?
if (zot(loopWait)) {loopWait = extraTime*tweek;}
if (zot(rewindWait)) {rewindWait = extraTime*tweek;}
}
// locally override call to add running status after animation done
var localCall = function() {
that.running = false;
that.stop();
if (call && typeof call == 'function') call(params||that);
};
zim.animate({
target:that,
obj:obj,
time:time,
ease:"linear",
call:localCall,
params:params,
wait:wait, waitedCall:waitedCall, waitedParams:waitedParams,
loop:loop,
loopCount:loopCount,
loopWait:loopWait,
loopCall:loopCall, loopParams:loopParams,
loopWaitCall:loopWaitCall, loopWaitParams:loopWaitParams,
rewind:rewind, rewindWait:rewindWait, // rewind is ignored by animation series
rewindCall:rewindCall, rewindParams:rewindParams,
rewindWaitCall:rewindWaitCall, rewindWaitParams:rewindWaitParams,
rewindTime:rewindTime, rewindEase:rewindEase,
override:false,
pauseOnBlur:pauseOnBlur,
id:that.id
});
that.runPaused = false;
return that;
};
this.runPaused = true;
this.pauseRun = function(paused) {
if (zot(paused)) paused = true;
that.runPaused = paused;
if (that.globalControl) {
zim.pauseAnimate(paused, that.id);
} else {
that.pauseAnimate(paused, that.id);
}
return that;
};
this.stopRun = function() {
that.runPaused = true;
that.running = false;
if (that.globalControl) {
zim.stopAnimate(that.id);
} else {
that.stopAnimate(that.id);
}
return that;
};
Object.defineProperty(this, 'frame', {
get: function() {
return this.currentFrame;
},
set: function(value) {
value = Math.round(value);
if (this.paused) {
this.gotoAndStop(value);
} else {
this.gotoAndPlay(value);
}
}
});
Object.defineProperty(this, 'normalizedFrame', {
get: function() {
return _normalizedFrame;
},
set: function(value) {
_normalizedFrame = Math.round(value);
this.gotoAndStop(_normalizedFrames[_normalizedFrame]);
}
});
Object.defineProperty(this, 'normalizedFrames', {
get: function() {
return _normalizedFrames;
},
set: function(value) {
_normalizedFrames = value;
}
});
Object.defineProperty(this, 'totalFrames', {
get: function() {
return sheet.getNumFrames();
},
set: function(value) {
zog("zim.Sprite - totalFrames is read only");
}
});
if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function() {
return this.cloneProps(new zim.Sprite(image, cols, rows, count, offsetX, offsetY, spacingX, spacingY, width, height, animations, json, null, globalControl, spriteSheet, label, frame, style, this.group, inherit));
};
var frame = zdf || 1;
if (createjs && !createjs.stageTransformable && frame.retina) {
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsSprite_localToGlobal);
};
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsSprite_globalToLocal);
};
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
};
}
this.hasProp = function(prop) {
return (!zot(this[prop]) || this.hasOwnProperty(prop));
};
zim.displayBase(that);
this.dispose = function(a,b,disposing) {
zim.gD(this); // globalDispose function for common elements
this.dispatchEvent("removed");
this.removeAllEventListeners();
if (this.parent) this.parent.removeChild(this);
};
};
zim.extend(zim.Sprite, createjs.Sprite, ["clone","localToLocal","localToGlobal","globalToLocal"], "cjsSprite", false);
zimify(zim.Sprite.prototype);
//-50.8
/*--
zim.MovieClip = function(mode, startPosition, loop, labels, style, group, inherit)
MovieClip
zim class - extends a createjs.MovieClip
DESCRIPTION
A MovieClip adds timelines to a Container.
The timelines are animate() zimTween properties.
The zimTween property returns a CreateJS Tween object.
Primarily made to support Adobe Animate MovieClip export.
*Consider this experimental for the moment...
NOTE: to use animate() on a MovieClip, add the MovieClip to a Container and animate() the Container
otherwise the animate() may advance the MovieClip.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var movieClip = new MovieClip();
var circle = new Circle(20, blue).animate({
props:{scale:3}, time:.1, rewind:true, loop:true
});
// Time is in frames NOT in ms - so 100 frames at the Ticker.framerate 60 fps by default is almost 2 seconds
// To change the Ticker's framerate use setFPS(mobile, desktop) method
// If you use one number then both mobile and desktop are set to that fps.
// The defaults are 60 fps mobile (as of ZIM Cat 04) and 60 fps desktop
movieClip.timeline.addTween(circle.zimTween);
movieClip.play();
movieClip.center();
stage.on("stagemousedown", function() {
movieClip.paused = !movieClip.paused;
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
// from the CreateJS MovieClip docs: http://www.createjs.com/docs/easeljs/classes/MovieClip.html
mode - (default "independent") or single_frame (based on startPosition) or synched (syncs to parent)
startPosition - (default 0) the start position of the MovieClip (*could not get to work)
loop - (default true) set to false not to loop (*did not seem to loop so use loop:true in zim.animate())
labels - (default null) declare label property with position value
eg. {explode:20} to use with gotoAndPlay("explode") rather than gotoAndPlay(20)
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for MovieClip methods, such as:
play(), gotoAndPlay(), gotoAndStop(), stop(), advance(),
on(), off(), getBounds(), setBounds(), dispatchEvent(), etc.
PROPERTIES
type - holds the class name as a String
draggable - set to true for a default drag() and false for a noDrag()
group - used when the object is made to add STYLE with the group selector (like a CSS class)
** bounds must be set first (or width and height parameters set) for these to work
** setting these adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
draggable - set to true for a default drag() and false for a noDrag()
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
effects - an object that holds effects added such as blur, glow, shadow, color, multi and alpha - see effect() under ZIM Methods
** the following are convenience Effects that run a ZIM MultiEffect()
** these can use a lot of processing when animating - see Docs for effects()
** batch versions are available too as hueBatch, etc. these will not update the effect until updateEffects() is called on the object
hue - the tint of an object between -180 and 180 with 0 being no change
saturation - the amount of color of an object between -100 and 100 with 0 being no change
brightness - the lightness or darkness of an object between -255 and 255 with 0 being no change
contrast - the crispness of an object between -100 and 100 with 0 being no change
ALSO: see the CreateJS Easel Docs for MovieClip properties, such as:
currentFrame, totalFrames, currentLabel, duration, framerate, labels, loop, mode, paused, startPosition, timeline,
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseEnabled, parent, etc.
EVENTS
See the CreateJS Easel Docs for MovieClip events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+50.9
zim.MovieClip = function(mode, startPosition, loop, labels, style, group, inherit) {
var sig = "mode, startPosition, loop, labels, style, group, inherit";
var duo; if (duo = zob(zim.MovieClip, arguments, sig, this)) return duo;
z_d("50.9");
this.type = "MovieClip";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(mode)) mode = DS.mode!=null?DS.mode:null;
if (zot(startPosition)) startPosition = DS.startPosition!=null?DS.startPosition:null;
if (zot(loop)) loop = DS.loop!=null?DS.loop:null;
if (zot(labels)) labels = DS.labels!=null?DS.labels:null;
this.cjsMovieClip_constructor(mode, startPosition, loop, labels);
if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function() {
return this.cloneProps(new zim.MovieClip(mode, startPosition, loop, labels, style, this.group, inherit));
};
this.hasProp = function(prop) {
return (!zot(this[prop]) || this.hasOwnProperty(prop));
};
var frame = zdf || 1;
if (createjs && !createjs.stageTransformable && frame.retina) {
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsMovieClip_localToGlobal);
};
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsMovieClip_globalToLocal);
};
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
};
}
zim.displayBase(this);
this.dispose = function(a,b,disposing) {
zim.gD(this); // globalDispose function for common elements
this.dispatchEvent("removed");
this.removeAllEventListeners();
if (this.parent) this.parent.removeChild(this);
};
};
zim.extend(zim.MovieClip, createjs.MovieClip, ["clone","localToLocal","localToGlobal","globalToLocal"], "cjsMovieClip", false);
zimify(zim.MovieClip.prototype);
//-50.9
/*--
zim.SVGContainer = function(svg, splitTypes, geometric, showControls, interactive, style, group, inherit)
SVGContainer
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Parses SVG and adds items to a ZIM Container.
Items are created as ZIM Shapes: Circle, Rectangle, Blob, Squiggle.
If geometric is true then Circle and Rectangle are used otherwise Blob is used.
Items can be accessed using svgcontainer.getChildAt(0), etc.
See: https://zimjs.com/svg/
See: https://zimjs.com/explore/svgcontainer.html
An SVG path string can be passed directly to a Squiggle or Blob points parameter
and so avoiding the SVGContainer - see ZIM Squiggle and Blob
WARNING: this should be considered experimental
The idea is that paths from SVG can be made editable in ZIM
or animation, dragging, or Label along paths can be accommodated
As such, not all SVG features will work - no CSS, Text, Gradients, DropShadows, etc.
It is possible that these will be added at some point
See also the ZIM svgToBitmap() function under META to get an exact image of the SVG
Thank you https://github.com/colinmeinke/svg-arc-to-cubic-bezier for the Arc conversion
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var svgContainer = new SVGContainer(asset("sample.svg")).addTo();
// OR
var svg = ``;
var svgContainer = new SVGContainer(svg).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
svg - an SVG file loaded into an asset() or SVG text
splitTypes - (default false) - set to true to split different types of paths into separate objects
geometric - (default true) - set to false to load Rectangle and Circle objects as Blob objects
showControls - (default true) set to false to start with controls not showing
interactive - (default true) set to false to turn off controls, move, toggle, select, edit - leaving just the shapes
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
processPath(path) - path is an SVG path string - returns a ZIM Blob or Squiggle points array
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
svg - a reference to the SVG text
type - holds the class name as a String
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+50.95
zim.SVGContainer = function(svg, splitTypes, geometric, showControls, interactive, style, group, inherit) {
var sig = "svg, splitTypes, geometric, showControls, interactive, style, group, inherit";
var duo; if (duo = zob(zim.SVGContainer, arguments, sig, this)) return duo;
z_d("50.95");
this.group = group;
var DS = style===false?{}:zim.getStyle("SVGContainer", this.group, inherit);
if (svg && svg.type == "Bitmap") svg = svg.svg; // svg is now loaded into a Bitmap automatically in Frame
var that = this;
var startPosition = new zim.Point(0,0); // the x,y of the last shape
var aCommand=[]; //kv adjust logic
var arcToBezier;
function makeArcCode() {
// ~~~~~~~~~~~~~~~~~~~~~~~~
// ES5 Babel port from ES6 https://github.com/colinmeinke/svg-arc-to-cubic-bezier
function _sa(arr, i) { return _ah(arr) || _il(arr, i) || _ua(arr, i) || _ni(); }
function _ni() { throw new TypeError("Invalid"); }
function _ua(o, minLen) { if (!o) return; if (typeof o === "string") return _ala(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _ala(o, minLen); }
function _ala(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _il(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _ah(arr) { if (Array.isArray(arr)) return arr; }
var TAU = Math.PI * 2;
var me = function me(_ref, rx, ry, cosphi, sinphi, centerx, centery) {
var x = _ref.x,
y = _ref.y;
x *= rx;
y *= ry;
var xp = cosphi * x - sinphi * y;
var yp = sinphi * x + cosphi * y;
return {
x: xp + centerx,
y: yp + centery
};
};
var approxUnitArc = function approxUnitArc(ang1, ang2) {
// If 90 degree circular arc, use a constant
// as derived from http://spencermortensen.com/articles/bezier-circle
var a = ang2 === 1.5707963267948966 ? 0.551915024494 : ang2 === -1.5707963267948966 ? -0.551915024494 : 4 / 3 * Math.tan(ang2 / 4);
var x1 = Math.cos(ang1);
var y1 = Math.sin(ang1);
var x2 = Math.cos(ang1 + ang2);
var y2 = Math.sin(ang1 + ang2);
return [{
x: x1 - y1 * a,
y: y1 + x1 * a
}, {
x: x2 + y2 * a,
y: y2 - x2 * a
}, {
x: x2,
y: y2
}];
};
var vectorAngle = function vectorAngle(ux, uy, vx, vy) {
var sign = ux * vy - uy * vx < 0 ? -1 : 1;
var dot = ux * vx + uy * vy;
if (dot > 1) {
dot = 1;
}
if (dot < -1) {
dot = -1;
}
return sign * Math.acos(dot);
};
var getArcCenter = function getArcCenter(px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinphi, cosphi, pxp, pyp) {
var rxsq = Math.pow(rx, 2);
var rysq = Math.pow(ry, 2);
var pxpsq = Math.pow(pxp, 2);
var pypsq = Math.pow(pyp, 2);
var radicant = rxsq * rysq - rxsq * pypsq - rysq * pxpsq;
if (radicant < 0) {
radicant = 0;
}
radicant /= rxsq * pypsq + rysq * pxpsq;
radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1);
var centerxp = radicant * rx / ry * pyp;
var centeryp = radicant * -ry / rx * pxp;
var centerx = cosphi * centerxp - sinphi * centeryp + (px + cx) / 2;
var centery = sinphi * centerxp + cosphi * centeryp + (py + cy) / 2;
var vx1 = (pxp - centerxp) / rx;
var vy1 = (pyp - centeryp) / ry;
var vx2 = (-pxp - centerxp) / rx;
var vy2 = (-pyp - centeryp) / ry;
var ang1 = vectorAngle(1, 0, vx1, vy1);
var ang2 = vectorAngle(vx1, vy1, vx2, vy2);
if (sweepFlag === 0 && ang2 > 0) {
ang2 -= TAU;
}
if (sweepFlag === 1 && ang2 < 0) {
ang2 += TAU;
}
return [centerx, centery, ang1, ang2];
};
return function arcToBezier(_ref2) {
var px = _ref2.px,
py = _ref2.py,
cx = _ref2.cx,
cy = _ref2.cy,
rx = _ref2.rx,
ry = _ref2.ry,
_ref2$xAxisRotation = _ref2.xAxisRotation,
xAxisRotation = _ref2$xAxisRotation === void 0 ? 0 : _ref2$xAxisRotation,
_ref2$largeArcFlag = _ref2.largeArcFlag,
largeArcFlag = _ref2$largeArcFlag === void 0 ? 0 : _ref2$largeArcFlag,
_ref2$sweepFlag = _ref2.sweepFlag,
sweepFlag = _ref2$sweepFlag === void 0 ? 0 : _ref2$sweepFlag;
var curves = [];
if (rx === 0 || ry === 0) {
return [];
}
var sinphi = Math.sin(xAxisRotation * TAU / 360);
var cosphi = Math.cos(xAxisRotation * TAU / 360);
var pxp = cosphi * (px - cx) / 2 + sinphi * (py - cy) / 2;
var pyp = -sinphi * (px - cx) / 2 + cosphi * (py - cy) / 2;
if (pxp === 0 && pyp === 0) {
return [];
}
rx = Math.abs(rx);
ry = Math.abs(ry);
var lambda = Math.pow(pxp, 2) / Math.pow(rx, 2) + Math.pow(pyp, 2) / Math.pow(ry, 2);
if (lambda > 1) {
rx *= Math.sqrt(lambda);
ry *= Math.sqrt(lambda);
}
var _getArcCenter = getArcCenter(px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinphi, cosphi, pxp, pyp),
_getArcCenter2 = _sa(_getArcCenter, 4),
centerx = _getArcCenter2[0],
centery = _getArcCenter2[1],
ang1 = _getArcCenter2[2],
ang2 = _getArcCenter2[3];
var ratio = Math.abs(ang2) / (TAU / 4);
if (Math.abs(1.0 - ratio) < 0.0000001) {
ratio = 1.0;
}
var segments = Math.max(Math.ceil(ratio), 1);
ang2 /= segments;
for (var i = 0; i < segments; i++) {
curves.push(approxUnitArc(ang1, ang2));
ang1 += ang2;
}
return curves.map(function (curve) {
var _me = me(curve[0], rx, ry, cosphi, sinphi, centerx, centery),
x1 = _me.x,
y1 = _me.y;
var _me2 = me(curve[1], rx, ry, cosphi, sinphi, centerx, centery),
x2 = _me2.x,
y2 = _me2.y;
var _me3 = me(curve[2], rx, ry, cosphi, sinphi, centerx, centery),
x = _me3.x,
y = _me3.y;
return {
x1: x1,
y1: y1,
x2: x2,
y2: y2,
x: x,
y: y
};
});
};
// ~~~~~~~~~~~~~~~~~~~~~~~~
}
if (zot(splitTypes)) splitTypes = false;
if (zot(geometric)) geometric = true;
if (!zot(svg)) {
if (svg.replace) svg = svg.replace(/style\s?=[^"]*"[^"]*"/ig, ""); // 10.9.0 remove style parameters
if (!zot(svg.draggable)) {
var parser = new DOMParser();
var svg = !svg.innerHTML?svg:parser.parseFromString(svg.innerHTML,"text/xml");
var list = svg.getElementsByTagName("svg");
var tag = this.svg = list?svg.getElementsByTagName("svg")[0]:null;
} else {
if (!svg.getAttribute) {
var parser = new DOMParser();
svg = parser.parseFromString(svg, "image/svg+xml").documentElement;
}
var tag = this.svg = svg;
}
var w, h;
if (!zot(tag)){
var w = tag.getAttribute("width");
var h = tag.getAttribute("height");
}
if (w) w = Number(w.trim());
if (h) h = Number(h.trim());
this.zimContainer_constructor(w, h);
this.type = "SVGContainer";
if (zot(tag)) return;
var defaultFill = zim.black, generalFill = zim.black;
var defaultStroke =zim. black, generalStroke = zim.black;
var defaultStrokeSize = 2, generalStrokeSize = 2;
var defaultAlpha = 1, generalAlpha = 1;
var defaultStrokeAlpha = 1, generalStrokeAlpha = 1;
var currentTransform;
function processTag(tag) {
zim.loop(tag, function (t) {
var tn = t.tagName.toLowerCase();
if (tn == "path") processPath(t);
if (tn == "circle") processShape("circle", t);
if (tn == "rect") processShape("rect", t);
if (tn == "ellipse") processShape("ellipse", t);
if (tn == "line") processShape("line", t);
if (tn == "polygon") processShape("polygon", t);
if (tn == "polyline") processShape("polyline", t);
if (tn == "g") {
// styles can be overwritten by parameters in the general tag
// so find styles first
var style = t.getAttribute("style");
var f,s,ss,a,aa;
if (style) {
var styles = processStyle(style);
f = styles[0];
s = styles[1];
ss = styles[2];
a = styles[3];
aa = styles[4];
}
// then overwrite styles with any attribute values
currentTransform = t.getAttribute("transform");
generalFill = t.getAttribute("fill")?t.getAttribute("fill"):!zot(f)?f:defaultFill;
generalStroke = t.getAttribute("stroke")?t.getAttribute("stroke"):!zot(s)?s:defaultStroke;
generalStrokeSize = t.getAttribute("stroke-width")?t.getAttribute("stroke-width"):!zot(ss)?ss:defaultStrokeSize;
generalAlpha = t.getAttribute("fill-opacity")?t.getAttribute("fill-opacity"):!zot(a)?a:defaultAlpha;
generalStrokeAlpha = t.getAttribute("stroke-opacity")?t.getAttribute("stroke-opacity"):!zot(aa)?aa:defaultStrokeAlpha;
}
// general settings can wrap any number of tags - the tags are processed here:
processTag(t.children);
// after this nest of tags are processed, clear the general settings
if (t.tagName.toLowerCase() == "g") {
generalFill = defaultFill;
generalStroke = defaultStroke;
generalStrokeSize = defaultStrokeSize;
generalAlpha = defaultAlpha;
generalStrokeAlpha = defaultStrokeAlpha;
currentTransform = null;
}
});
}
var process = svg.getElementsByTagName("svg");
if (process.length == 0) process = [svg];
function processStyle(style) {
var st = style.split(";"); //kv note: there si bug when style contains ; at the end of the string
var f,s,ss,a,aa;
zim.loop(st, function (sty) {
var sty = sty.replace(/,/g,"");
var styl = sty.split(":");
var prop = styl[0].trim().toLowerCase();
var val = styl[1].trim().toLowerCase().replace("px", "");
if (prop=="fill") f = val;
if (prop=="stroke") s = val;
if (prop=="stroke-width") ss = val;
if (prop=="opacity") a = val, aa = val;
if (prop=="fill-opacity") a = val;
if (prop=="stroke-opacity") aa = val;
});
return [f,s,ss,a,aa];
}
function processShape(type, tag) {
var shape;
var g = processGeneral(tag); // want ES6
var f = g[0], s = g[1], ss = g[2], a = g[3], aa = g[4], x = g[5], y = g[6];
if (type == "circle") {
var r = Number(tag.getAttribute("r").trim());
var d = r*.5523;
if (geometric) shape = new zim.Circle(Number(tag.getAttribute("r")), f, s, ss);
else shape = new zim.Blob(f, s, ss, 4, r, d, "mirror", null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
} else if (type == "rect") {
if (geometric) shape = new zim.Rectangle(Number(tag.getAttribute("width")), Number(tag.getAttribute("height")), f, s, ss, Number(tag.getAttribute("rx")));
else {
var w = Number(tag.getAttribute("width"));
var h = Number(tag.getAttribute("height"));
var rx = Number(tag.getAttribute("rx"));
var ry = Number(tag.getAttribute("ry"));
if (rx && ry) {
var dx = rx*.5523;
var dy = ry*.5523;
shape = new zim.Blob(f, s, ss, [
[rx,0,0,0,-dx,0,0,0,"free"],[w-rx,0,0,0,0,0,dx,0,"free"],
[w,ry,0,0,0,-dy,0,0,"free"],[w,h-ry,0,0,0,0,0,dy,"free"],
[w-rx,h,0,0,dx,0,0,0,"free"],[rx,h,0,0,0,0,-dx,0,"free"],
[0,h-ry,0,0,0,dy,0,0,"free"],[0,ry,0,0,0,0,0,-dy,"free"]], null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
} else {
shape = new zim.Blob(f, s, ss, [[0,0],[w,0],[w,h],[0,h]], null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
}
}
} else if (type == "line") {
shape = new zim.Squiggle(s, ss, [[Number(tag.getAttribute("x1")), Number(tag.getAttribute("y1"))],[Number(tag.getAttribute("x2")), Number(tag.getAttribute("y2"))]], null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
} else if (type == "polygon" || type == "polyline") {
var p = tag.getAttribute("points");
p = p.replace(/-/g, " -");
p = p.replace(/\s+/g, " ");
var points = [];
if (p.indexOf(",") != -1) {
zim.loop(p.split(" "), function (point) {
var pp = point.split(",");
points.push([Number(pp[0].trim()), Number(pp[1].trim())]);
});
} else {
var lastP;
zim.loop(p.split(" "), function (point, i) {
if ((i+1)%2==0) points.push([lastP, point.trim()]);
lastP = point.trim();
});
}
if (type=="polygon") shape = new Blob(f, s, ss, points);
else shape = new zim.Squiggle(s, ss, points, null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
} else if (type == "ellipse") {
shape = new zim.Blob(f, s, ss, ellipse(0, 0, Number(tag.getAttribute("rx")), Number(tag.getAttribute("ry"))), null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
}
shape.loc(x,y,that);
var transform = tag.getAttribute("transform");
if (transform || currentTransform) processTransform(shape, transform || currentTransform);
if (interactive && (shape.type == "Rectangle" || shape.type=="Circle")) shape.transform({showReg:false, visible:showControls});
}
function processTransform(shape, transform) {
var tr = transform.split(")");
// apply all transforms in the order given
zim.loop(tr, function (tra) {
if (tra=="") return;
var tran = tra.trim().split("(");
var prop = tran[0].trim().toLowerCase();
var val = tran[1].trim().toLowerCase().replace("px", "").replace("deg", "");
if (prop=="translate") {
var m = val.split(",");
shape.mov(Number(m[0].trim()), m[1]?Number(m[1].trim()):0);
}
if (prop=="scale"){
var s = val.split(",");
if (shape.type=="Blob" || shape.type=="Squiggle") {
if (s.length == 1) shape.transformPoints("scale", Number(s[0].trim()));
else if (s.length == 2) {
shape.transformPoints("scaleX", Number(s[0].trim()));
shape.transformPoints("scaleY", Number(s[1].trim()));
}
} else {
if (s.length == 1) shape.sca(Number(s[0].trim()));
else if (s.length == 2) {
shape.sca(Number(s[0].trim()), Number(s[1].trim()));
}
}
}
if (prop=="rotate") {
var r = val.split(",");
// if (shape.type=="Blob" || shape.type=="Squiggle") {
// rotation is a different way for SVG and transform() - too bad
// it rotates around 0,0 unless a different point is chosen
// so shape.transformPoints which is a registration point system
// is unlikely to work - and too complex to add rotate around a given point
// so we will use zim rot() to which we have added rotating around a different point
// but this will rotate the little box handles
// maybe look into keeping those parallel in the blob and squiggle - no matter what the rotation
// if (r.length == 1) shape.transformPoints("rotation", Number(r[0].trim()))
if (r.length == 1) r.push(0,0);
else if (r.length == 2) r.push(0);
shape.rot(Number(r[0].trim()), Number(r[1].trim()), Number(r[2].trim()));
}
if (prop=="skewX") shape.skewX = val;
if (prop=="skewY") shape.skewY = val;
});
}
// beatgammit on StackOverflow
function ellipse(x, y, xDis, yDis) {
var kappa = 0.5522848, // 4 * ((√(2) - 1) / 3)
ox = xDis * kappa, // control point offset horizontal
oy = yDis * kappa, // control point offset vertical
xe = x + xDis, // x-end
ye = y + yDis; // y-end
var points = [ // modified by Dan Zen to relative
[x - xDis, y, 0, 0, x, ye+oy-yDis, x, y-oy, "mirror"],
[x, y - yDis, 0, 0, x-ox, y, xe+ox-xDis, y, "mirror"],
[xe, y, 0, 0, x, y-oy, x + ox-ox, ye+oy-yDis, "mirror"],
[x, ye, 0, 0, xe-xDis+ox, y, x-ox, y, "mirror"]
];
return points;
}
processTag(process);
}
function processGeneral(tag) {
// any styles on the tag overwrites general styles or attributes
var f,s,ss,a,aa;
var style = tag.getAttribute("style");
if (style) {
var styles = processStyle(style);
f = styles[0];
s = styles[1];
ss = styles[2];
a = styles[3];
aa = styles[4];
}
// kv comments: need to apply string cleansing, application bugs when there is a semi colon character used in tags.
// get rid of semi colon,
// any attributes on the tag overwrites styles or general
f = tag.getAttribute("fill")?tag.getAttribute("fill"):!zot(f)?f:generalFill;
s = tag.getAttribute("stroke")?tag.getAttribute("stroke"):!zot(s)?s:generalStroke;
ss = tag.getAttribute("stroke-width")?tag.getAttribute("stroke-width"):!zot(ss)?ss:generalStrokeSize;
a = tag.getAttribute("fill-opacity")?tag.getAttribute("fill-opacity"):!zot(a)?a:generalAlpha;
aa = tag.getAttribute("stroke-opacity")?tag.getAttribute("stroke-opacity"):!zot(aa)?aa:generalStrokeAlpha;
var x = tag.getAttribute("x")?tag.getAttribute("x"):0;
x = tag.getAttribute("cx")?tag.getAttribute("cx"):x;
var y = tag.getAttribute("y")?tag.getAttribute("y"):0;
y = tag.getAttribute("cy")?tag.getAttribute("cy"):y;
if (!zot(a) && !zot(f)) f = zim.convertColor(f, "rgba", Number(a));
if (!zot(aa) && !zot(s)) s = zim.convertColor(s, "rgba", Number(aa));
return [f,s,Number(ss),Number(a),Number(aa),Number(x),Number(y)];
}
function processPath (path, make) {
if (zot(make)) make = true;
var commands = ["M","m","L","l","H","h","V","v","C","c","S","s","Q","q","T","t","A","a","z","Z"];
var commandsRelative = ["m","l","h","v","c","s","q","t","a","z"];
var position = new zim.Point(0,0); // the current position - relative places based on this
if (zot(path.getAttribute)) {
var d = path;
} else {
var id = path.getAttribute("id");
var d = path.getAttribute("d");
}
// m251.85 119.04c7.85 10.45-9.81
d = d.replace(/,/g ," ");
d = d.replace(/([a-zA-Z])/g, " $1 ");
d = d.replace(/-/g, " -");
d = d.replace(/\s+/g, " ");
// can also bump decimal numbers together if one decimal place in first - sigh... Cat 01
// 10.93.12 is really 10.93 .12
d = d.replace(/\.(\d*)\./g, ".$1 .");
if (make) {
var g = processGeneral(path); // want ES6
var f = g[0]; var s = g[1]; var ss = g[2]; var a = g[3]; var aa = g[4];
}
var shape; //kv adjust logic
var aNumber; //kv adjust logic
//var points = [[0,0]]; //kv adjust logic
var points = []; //kv adjust logic
var lastTempPoint = [0,0]; //kv adjust logic
var line = new zim.Point(0,0);
var quad = new zim.Point(0,0,0,0);
var cube = new zim.Point(0,0,0,0,0,0);
var arc = new zim.Point(0,0,0,0,0,0,0);
//kv var data = d.split(" "); //kv adjust logic
var dataOrigin = d.split(" "); //kv adjust logic
var data = dataOrigin.slice(1,dataOrigin.length); //kv adjust logic
var aCommand = []; //kv adjust logic
var missingCommand = false; //not used yet //kv adjust logic
var lastCommand = ""; //kv adjust label
var previousCommand = ""; //not used yet //kv adjust logic
var adding = false;
var what;
var type = "squiggle";
var dataType = null;
//kv loop(data, function (command) { //kv adjust logic
zim.loop(data, function (command, i) { //kv adjust logic
if (i==0) {
startPosition.x = 0;
startPosition.y = 0;
lastTempPoint = [0,0];
lastCommand = "";
previousCommand = "";
}
if (commands.indexOf(command) == -1) {
if (what == "lxo") {what="lx"; aCommand.push("l");missingCommand=true;} //kv adjust logic
if (what == "lyo") {what="ly"; missingCommand=true;} //kv adjust logic
if (what == "Lxo") {what="Lx"; aCommand.push("L");missingCommand=true;} //kv adjust logic
if (what == "Lyo") {what="Ly"; missingCommand=true;} //kv adjust logic
aNumber = Number(command); //kv adjust logic
aNumber = Math.round(aNumber * 100) / 100; //kv adjust logic
// position
if (what == "X") {
startPosition.x = aNumber;
what = "Y";
} else if (what == "Y") {
startPosition.y = aNumber;
//kv what = "Lx"; // in case no letters come next //kv adjust logic
what = "Lxo"; // in case no letters come next //kv adjust logic
points.push([startPosition.x, startPosition.y]); //kv adjust logic
// what = null;
} else if (what == "x") {
//if (points.length > 1) {
// startPosition.x = points[points.length-1][0]; //kv adjust logic
// startPosition.y = points[points.length-1][1] //kv adjust logic
//} else {
// startPosition.x = lastTempPoint[0]; //kv adjust logic
// startPosition.y = lastTempPoint[1] //kv adjust logic
//};
startPosition.x = startPosition.x+aNumber;
what = "y";
} else if (what == "y") {
startPosition.y = startPosition.y+aNumber;
what = "lxo"; //kv adjust logic
//kv what = "lx"; // in case no letters come next //kv adjust logic
points.push([startPosition.x, startPosition.y]); //kv adjust logic
// what = null;
}
// left, right, top or bottom
if (what == "H" || what == "h") {
position.x = points[points.length-1][0]; //kv adjust logic
position.y = points[points.length-1][1]; //kv adjust logic
position.x = position.x + (what=="h"?aNumber:aNumber-startPosition.x);
points.push([position.x, position.y]);
what = "Lx";
} else if (what == "V" || what == "v") {
position.x = points[points.length-1][0]; //kv adjust logic
position.y = points[points.length-1][1]; //kv adjust logic
position.y = position.y + (what=="v"?aNumber:aNumber-startPosition.y);
points.push([position.x, position.y]);
what = "lx";
}
// line
if (what == "Lx") {
//kv line.x = aNumber-startPosition.x; //kv adjust logic
line.x = aNumber; //kv adjust logic
what = "Ly";
} else if (what == "Ly") {
//kv line.y = aNumber-startPosition.y; //kv adjust logic
line.y = aNumber; //kv adjust logic
position.x = line.x;
position.y = line.y;
points.push([position.x, position.y]);
what = "Lx";
} else if (what == "lx") {
if (aCommand.length > 0) { //kv adjust logic
if (position.x != 0 && position.y != 0 ) {
startPosition.x = position.x;
startPosition.y = position.y;
}
else {
startPosition.x = position.x + startPosition.x; //kv adjust logic
startPosition.y = position.y + startPosition.y; //kv adjust logic
//startPosition.x = position.x + lastTempPoint[0]; //kv adjust logic
//startPosition.y = position.y + lastTempPoint[1]; //kv adjust logic
}
} //kv adjust logic
line.x = startPosition.x + aNumber; //kv adjust logic
//kv line.x = line.x + aNumber; //kv adjust logic
if (missingCommand) {what="lyo";} else //kv adjust logic
what = "ly";
} else if (what == "ly") {
line.y = startPosition.y + aNumber; //kv adjust logic
//line.y = line.y + aNumber; //kv adjust logic
position.x = line.x;
position.y = line.y;
points.push([position.x, position.y]);
what = "lx";
}
// Quadratic
if (what == "qx" || what == "Qx") {
if (points.length > 0) { //kv adjust logic
startPosition.x = points[points.length-1][0]; //kv adjust logic
startPosition.y = points[points.length-1][1]; //kv adjust logic
} else { //kv adjust logic
startPosition.x = 0; //kv adjust logic
startPosition.y = 0; //kv adjust logic
} //kv adjust logic
//kv quad.x = what=="qx"?position.x+aNumber:aNumber-startPosition.x;
quad.x = what=="qx"?startPosition.x+aNumber:aNumber; //kv adjust logic
what = what=="qx"?"qy":"Qy";
} else if (what == "qy" || what == "Qy") {
//kv quad.y = what=="qy"?position.y+aNumber:aNumber-startPosition.y;
quad.y = what=="qy"?startPosition.y+aNumber:aNumber; //kv adjust logic
what = what=="qy"?"qz":"Qz";
if (adding) {
adding = false;
var lastPoint = points[points.length-1];
lastPoint[6] = -lastPoint[4];
lastPoint[7] = -lastPoint[5];
lastPoint[8] = "mirror";
position.x = quad.x;
position.y = quad.y;
points[points.length] = [
position.x, position.y,
0, 0,
-lastPoint[6], lastPoint[7],
0,0,
"free"
];
what = what=="qy"?"qx":"Qx";
}
} else if (what == "qz" || what == "Qz") {
//kv quad.z = what=="qz"?position.x+aNumber:aNumber-startPosition.x;
quad.z = what=="qz"?startPosition.x+aNumber:aNumber; //kv adjust logic
what = what=="qz"?"qq":"Qq";
} else if (what == "qq" || what == "Qq") {
//kv quad.w = what=="qq"?position.y+aNumber:aNumber-startPosition.y;
quad.w = what=="qq"?startPosition.y+aNumber:aNumber; //kv adjust logic
var lastPoint = points[points.length-1];
position.x = lastPoint[0]; //kv adjust logic
position.y = lastPoint[1]; //kv adjust logic
if (points.length == 1) { //kv adust logic
lastPoint[2] = 0; lastPoint[3] = 0; lastPoint[4] = 0; lastPoint[5] = 0; //kv adjust logic //kv debug
lastPoint[6] = 2/3 *(quad.x - position.x); // relative needs position and absolute does not it
lastPoint[7] = 2/3 *(quad.y - position.y);
lastPoint[8] = "free";
} //kv adjust logic
else { //kv adjust logic
points[points.length] = [ //kv adjust logic
position.x, position.y, //kv adjsut logic
0, 0, 0, 0, //kv adjust logic
2/3*(quad.x-position.x), //kv adjust logic
2/3*(quad.y-position.y), //kv adjust logic
"free" //kv adjust logic
]; //kv adjust logic
} //kv adjust logic
position.x = quad.z; // assign this point's position - fix this and apply throughout...
position.y = quad.w;
points[points.length] = [
position.x, position.y,
0, 0,
// relative needs - startPosition and absolute does not
2/3*(quad.x-position.x), 2/3*(quad.y-position.y),
0,0,
"free"
];
what = what=="qq"?"qx":"Qx";
}
// Cubic
if (what == "cx" || what == "Cx") {
if (points.length > 0) { //kv adjust logic
startPosition.x = points[points.length-1][0]; //kv adjust logic
startPosition.y = points[points.length-1][1]; //kv adjust logic
} else { //kv adjust logic
startPosition.x = 0; //kv adjust logic
startPosition.y = 0; //kv adjust logic
} //kv adjust logic
//kv cube.x = what=="cx"?position.x+aNumber:aNumber-startPosition.x;
cube.x = what=="cx"?startPosition.x+aNumber:aNumber; //kv adjust logic
what = what=="cx"?"cy":"Cy";
} else if (what == "cy" || what == "Cy") { // y Control Point 1
//kv cube.y = what=="cy"?position.y+aNumber:aNumber-startPosition.y;
cube.y = what=="cy"?startPosition.y+aNumber:aNumber; //kv adjust logic
what = what=="cy"?"cz":"Cz";
} else if (what == "cz" || what == "Cz") { // x Control Point 2
//kv cube.z = what=="cz"?position.x+aNumber:aNumber-startPosition.x;
cube.z = what=="cz"?startPosition.x+aNumber:aNumber; //kv adjust logic
what = what=="cz"?"cq":"Cq";
} else if (what == "cq" || what == "Cq") { // y Control Point 2
//kv cube.q = what=="cq"?position.y+aNumber:aNumber-startPosition.y;
cube.q = what=="cq"?startPosition.y+aNumber:aNumber; //kv adjust logic
what = what=="cq"?"cr":"Cr";
if (adding) {
if (lastCommand=="s") {previousCommand = "s";} else {previousCommand = "S";}
//kv adding = false;
//kv update previous point
var lastPoint = points[points.length-1];
lastPoint[2] = 0; //kv adjust logic
lastPoint[3] = 0; //kv adjust logic
if(zot(lastPoint[4])) {lastPoint[4] =0;} //kv adjust logic
if(zot(lastPoint[5])) {lastPoint[5] =0;} //kv adjust logic
lastPoint[6] = -lastPoint[4];
lastPoint[7] = -lastPoint[5];
// lastPoint[6] = - (cube.x-cube.z); //kv adjust logic
// lastPoint[7] = - (cube.y-cube.q); //kv adjust logic
lastPoint[8] = "mirror";
//kv create very lastPoint
position.x = cube.z;
position.y = cube.q;
points[points.length] = [
position.x, position.y,
0, 0,
cube.x-position.x, cube.y-position.y,
0,0,
"free"
];
//kv what = what=="cq"?"cx":"Cx";
what = what=="cr"?"cx":"Cx"; //kv adjust logic
}
} else if (what == "cr" || what == "Cr") {
//kv cube.r = what=="cr"?position.x+aNumber:aNumber-startPosition.x;
cube.r = what=="cr"?startPosition.x+aNumber:aNumber; //kv adjust logic
what = what=="cr"?"cs":"Cs";
} else if (what == "cs" || what == "Cs") { // y 2nd Point
//kv cube.s = what=="cs"?position.y+aNumber:aNumber-startPosition.y;
cube.s = what=="cs"?startPosition.y+aNumber:aNumber; //kv adjust logic
//points.push([cube.r, cube.s]); //kv adjust logic
//[controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType], //kv debug
var lastPoint = points[points.length-1];
if (points.length == 1) {lastPoint[2] = 0; lastPoint[3] = 0; lastPoint[4] = 0; lastPoint[5] = 0;} //kv adjust logic
lastPoint[6] = cube.x-lastPoint[0];
lastPoint[7] = cube.y-lastPoint[1];
lastPoint[8] = "free";
position.x = cube.r;
position.y = cube.s;
points[points.length] = [
position.x, position.y,
0, 0,
cube.z-position.x, cube.q-position.y,
0,0,
"free"
];
what = what=="cs"?"cx":"Cx";
// Arc
// https://github.com/colinmeinke/svg-arc-to-cubic-bezier/issues/7
// rx ry x-axis-rotation large-arc-flag sweep-flag x y
} else if (what == "ax" || what == "Ax") {
if (points.length > 0) {
startPosition.x = points[points.length-1][0];
startPosition.y = points[points.length-1][1];
} else {
startPosition.x = 0;
startPosition.y = 0;
}
arc.x = aNumber; // radius x
what = what=="ax"?"ay":"Ay";
} else if (what == "ay" || what == "Ay") {
arc.y = aNumber; // radius y
what = what=="ay"?"az":"Az";
} else if (what == "az" || what == "Az") {
arc.z = aNumber; // x-axis-rotation
what = what=="az"?"aq":"Aq";
} else if (what == "aq" || what == "Aq") {
arc.q = aNumber; // large-arc-flag
what = what=="aq"?"ar":"Ar";
} else if (what == "ar" || what == "Ar") {
arc.r = aNumber; // sweep-flag
what = what=="ar"?"as":"As";
} else if (what == "as" || what == "As") {
arc.s = what=="as"?startPosition.x+aNumber:aNumber;
what = what=="as"?"at":"At";
} else if (what == "at" || what == "At") {
arc.t = what=="at"?startPosition.y+aNumber:aNumber;
// rx ry x-axis-rotation large-arc-flag sweep-flag x y
if (!arcToBezier) arcToBezier = makeArcCode();
var curves = arcToBezier({
px: startPosition.x,
py: startPosition.y,
cx: arc.s,
cy: arc.t,
rx: arc.x,
ry: arc.y,
xAxisRotation: arc.z,
largeArcFlag: arc.q,
sweepFlag: arc.r,
});
loop(curves, function (curve, ii) {
lastPoint = points[points.length-1];
if (points.length == 1) {lastPoint[2] = 0; lastPoint[3] = 0; lastPoint[4] = 0; lastPoint[5] = 0;} //kv adjust logic
if (ii==0 && points.length == 1) {
lastPoint[6] = curve.x1-position.x-startPosition.x;
lastPoint[7] = curve.y1-position.y-startPosition.y;
} else {
lastPoint[6] = curve.x1-position.x;
lastPoint[7] = curve.y1-position.y;
}
lastPoint[8] = "free";
position.x = curve.x;
position.y = curve.y;
points[points.length] = [
position.x, position.y,
0, 0,
curve.x2-position.x, curve.y2-position.y,
0,0,
"free"
];
});
what = what=="at"?"ax":"Ax";
}
}
else {
aCommand.push(command); // kv adjust logic
// Commands
if (command != "s") {
adding = false;
} // kv adjust logic
if (aCommand.length > 1) { // kv adjust logic
// if (aCommand[aCommand.length-2] != command) {
if (command=="M" || command=="m") {
makeShape(aCommand);
if (command=="M") {startPosition.x = 0; startPosition.y=0;}
else {
startPosition.x = points[points.length-1][0]; startPosition.y=points[points.length-1][1];
}
points = [];
aCommand = [];
aCommand.push(command);
}
} // kv adjust logic
if (command=="M") {
what = "X";
} else if (command=="m") {
what = "x";
} else if (command=="L") {
what = "Lx";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="l") {
what = "lx";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="H") {
what = "H";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="h") {
what = "h";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="V") {
what = "V";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="v") {
what = "v";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="C") {
what = "Cx";
if (splitTypes && dataType && (dataType != "c")) makeShape(aCommand);
dataType = "c";
} else if (command=="c") {
what = "cx";
if (splitTypes && dataType && (dataType != "c")) makeShape(aCommand);
dataType = "c";
} else if (command=="S") {
adding = true;
what = "Cx";
if (splitTypes && dataType && (dataType != "c")) makeShape(aCommand);
dataType = "c";
} else if (command=="s") {
adding = true;
what = "cx";
if (splitTypes && dataType && (dataType != "c")) makeShape(aCommand);
dataType = "c";
} else if (command=="Q") {
what = "Qx";
if (splitTypes && dataType && (dataType != "q")) makeShape(aCommand);
dataType = "q";
} else if (command=="q") {
what = "qx";
if (splitTypes && dataType && (dataType != "q")) makeShape(aCommand);
dataType = "q";
} else if (command=="T") {
adding = true;
what = "Qx";
if (splitTypes && dataType && (dataType != "q")) makeShape(aCommand);
dataType = "q";
} else if (command=="t") {
adding = true;
what = "qx";
if (splitTypes && dataType && (dataType != "q")) makeShape(aCommand);
dataType = "q";
} else if (command=="A") {
// type = null;
what = "Ax";
if (splitTypes && dataType && (dataType != "a")) makeShape();
dataType = "a";
} else if (command=="a") {
what = "ax";
if (splitTypes && dataType && (dataType != "a")) makeShape();
dataType = "a";
} else if (command=="z" || command=="Z") {
type = "blob";
}
} // end of Command process
}); // end of data loop
function makeShape(myCommand, interest) {
var myCommand;
//var shape; //kv adjust logic
lastCommand = aCommand[aCommand.length-1]; //kv adjust logic
if (points.length >= 2)
// M 100 350 l 150 -300
if (lastCommand == "z" || lastCommand == "Z") {type = "blob";} //kv adjust logic
//if (zot(shape)) { //kv adjust logic
if (type == "squiggle") shape = new zim.Squiggle(s, ss, points, null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
else shape = new zim.Blob(f, s, ss, points, null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
shape.loc(0,0,that); //kv adjust logic
//} else { //kv adjust logic
// var dataPointsArray = []; //kv adjust logic
// dataPointsArray = shape.recordPoints().concat(points); //kv adjust logic
// //shape.removeFrom(); //kv adjust logic
// if (type == "squiggle") shape = new Squiggle(s, ss, dataPointsArray) //kv adjust logic
// else shape = new Blob(f, s, ss, dataPointsArray) //kv adjust logic
//};
//kv shape.loc(startPosition.x, startPosition.y, that); //kv adjust logic
//kv startPosition.x = startPosition.x + position.x; //kv adjust logic
//kv startPosition.y = startPosition.y + position.y; //kv adjust logic
lastCommand = aCommand[aCommand.length-1]; //kv adjust logic
previousCommand = aCommand[aCommand.length-2]; //kv adjust logic
if (commandsRelative.indexOf(lastCommand) >= 0) {
//if (aCommand[aCommand.length-1] == "m") { //kv adjust logic
lastTempPoint[0] = points[points.length-1][0]; lastTempPoint[1] = points[points.length-1][1]; //kv adjust logic
startPosition.x = points[points.length-1][0]; startPosition.y = points[points.length-1][1]; //kv adjust logic
points = []; // LATEST CHANGES
points.push([lastTempPoint[0], lastTempPoint[1]]); //kv adjust logic
} else {lastTempPoint = [0,0]; points = [[0,0]];}
aCommand = []; //kv adjust logic
if (lastCommand != "z" && lastCommand != "Z") aCommand.push(lastCommand); //kv adjust logic
position.x = 0;
position.y = 0;
//kv points = [[0,0]];
var transform = path.getAttribute("transform");
if (transform || currentTransform) processTransform(shape, transform || currentTransform);
}
if (make) makeShape();
return points;
} // end process path
that.processPath = function(path) {
return processPath(path,false);
};
if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function() {
return that.cloneProps(new zim.SVGContainer(svg, splitTypes, geometric, showControls, interactive, style, this.group, inherit));
};
};
zim.extend (zim.SVGContainer, zim.Container, "clone", "zimContainer", false);
//-50.95
// SUBSECTION ZIM SHAPES
/*--
zim.CustomShape = function(x, y, w, h)
CustomShape
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Used internally to make ZIM Shapes - Circle, Rectangle, Triangle, etc.
Holds the following properties in common:
color, colorRange, borderColor, borderWidth, thickness, dashed, dashedOffset, corner
Holds the following functions in common: (most methods applied through ZIM 4TH methods)
setColorRange, cloneAll(), linearGradient (depreciated), radialGradient (depreciated)
NOTE: this is NOT a generic Shape - see the zim.Shape() class for that.
EXAMPLE
// would recommend just extending a Container() for custom shapes / objects
// unless properties listed above are needed over multiple projects
// but it could be done with matching various private properties, etc.
// also note that a Blob can make just about any shape...
var Smile = function(color) {
this.super_constructor(-100,-20,200,70);
this._color = color;
this.shape = new Shape().addTo(this);
// this is an example of how ZIM changes shape color
// will need to go through and do similar things for borderColor, etc.
this.colorCommand = this.shape.f(this._color).command;
this.shape.mt(-100,-20).bt(0,70,0,70,100,-20);
}
extend(Smile, CustomShape);
var smile = new Smile(red).center();
timeout(1, function () {
smile.color = blue;
stage.update();
});
END EXAMPLE
SEE - ZIM shapes for details.
--*///+50.97
zim.CustomShape = function(x, y, w, h) {
if (!zim.zimCustomShapeCheck) {z_d("50.97"); zim.zimCustomShapeCheck=true;}
this.zimContainer_constructor(x, y, w, h, false);
var that = this;
this.mouseChildren = false;
that._dashedOffset = 5;
Object.defineProperty(that, 'color', {
get: function() {
return that._color;
},
set: function(value) {
if (zot(value)) value = "black";
that._color = value;
if (value && value.type) that.specialColor(that.colorCommand, value);
else that.colorCommand.style = value;
}
});
this.setColorRange = function(color1, color2) {
if (zot(color2)) {
that.startColor = that.color;
that.endColor = color1;
} else if (zot(color1)) {
that.startColor = that.color;
that.endColor = color2;
} else {
that.startColor = color1;
that.endColor = color2;
}
return that;
};
that._colorRange = 0;
Object.defineProperty(that, 'colorRange', {
get: function() {
return that._colorRange;
},
set: function(value) {
that._colorRange = value;
if (!zot(that.startColor) && !zot(that.endColor)) {
that.color = zim.colorRange(that.startColor, that.endColor, value);
}
}
});
Object.defineProperty(that, 'borderColor', {
get: function() {
return that._borderColor;
},
set: function(value) {
that._borderColor = value;
if (value && !that.borderWidth) {
that.borderWidth = 1;
}
if (!that.borderColorCommand) {
that.drawShape();
}
else if (value && value.type) that.specialColor(that.borderColorCommand, value);
else that.borderColorCommand.style = value;
}
});
Object.defineProperty(that, 'borderWidth', {
get: function() {
return that._borderWidth;
},
set: function(value) {
if (!(value>0)) value = 0;
that._borderWidth = value;
if (!that.borderWidthCommand || that._borderWidth == 0) {
that.borderWidthCommand = null;
that.drawShape();
}
else {
that.borderWidthCommand.width = that._borderWidth;
if (that._dashed) {
that.borderDashedCommand.segments = that._dashed;
that.borderDashedCommand.offset = that._dashedOffset;
}
}
}
});
Object.defineProperty(that, 'thickness', {
get: function() {
return that._thickness;
},
set: function(value) {
if (!(value>0)) value = 0;
that._thickness = value;
if (!that.thicknessCommand || that._thickness == 0) that.drawShape();
else {
that.thicknessCommand.width = that._thickness;
if (that._dashed) {
that.dashedCommand.segments = that._dashed;
that.dashedCommand.offset = that._dashedOffset;
}
}
}
});
Object.defineProperty(that, 'dashed', {
get: function() {
return that._dashed;
},
set: function(value) {
that._dashed = value;
if (value && !Array.isArray(that._dashed)) that.dashed = [10, 10];
if (that.type == "Squiggle" || that.type == "Line") {
if (!that.thicknessCommand || that._thickness == 0) return;
var dashedCommand = that.dashedCommand;
} else {
if (!that.borderWidthCommand || that._borderWidth == 0) return;
var dashedCommand = that.borderDashedCommand;
}
if (!dashedCommand) {
that.drawShape();
} else {
if (that._dashed) {
dashedCommand.segments = that._dashed;
dashedCommand.offset = that._dashedOffset;
} else {
dashedCommand.segments = null;
dashedCommand.offset = null;
}
}
}
});
Object.defineProperty(that, 'dashedOffset', {
get: function() {
return that._dashedOffset;
},
set: function(value) {
if (isNaN(value)) value = 5;
that._dashedOffset = value;
if (that.type == "Squiggle" || that.type == "Line") {
if (!that.thicknessCommand || that._thickness == 0) return;
var dashedCommand = that.dashedCommand;
} else {
if (!that.borderWidthCommand || that._borderWidth == 0) return;
var dashedCommand = that.borderDashedCommand;
}
if (!dashedCommand) {
that.drawShape();
} else {
if (that._dashed) {
dashedCommand.segments = that._dashed;
dashedCommand.offset = that._dashedOffset;
} else {
dashedCommand.segments = null;
dashedCommand.offset = null;
}
}
}
});
Object.defineProperty(that, 'corner', {
get: function() {
return that._corner;
},
set: function(value) {
that._corner = value;
that.drawShape();
}
});
// depreciated
this.linearGradient = function(colors,ratios,x0,y0,x1,y1) {
this.linearGradientParams = Array.prototype.slice.call(arguments);
this.colorCommand.linearGradient(colors,ratios,x0,y0,x1,y1);
return this;
};
this.radialGradient = function(colors,ratios,x0,y0,radius0,x1,y1,radius1) {
this.radialGradientParams = Array.prototype.slice.call(arguments);
this.colorCommand.radialGradient(colors,ratios,x0,y0,radius0,x1,y1,radius1);
return this;
};
// special clone that clones contents of shape
this.cloneAll = function(exact, style, group, inherit) {
var currentBounds = this.getBounds();
if (zot(currentBounds)) currentBounds = {x:null, y:null, width:null, height:null};
var body = this.cloneChildren(this.cloneProps(new zim.Container(currentBounds.x,currentBounds.y,currentBounds.width,currentBounds.height, style, group, inherit)), exact);
body.mouseChildren = false;
body.type = this.type;
return body;
};
};
zim.extend(zim.CustomShape, zim.Container, null, "zimContainer", false);
//-50.97
/*--
zim.Circle = function(radius, color, borderColor, borderWidth, dashed, percent, percentClose, strokeObj, style, group, inherit)
Circle
zim class - extends a zim.CustomShape which extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a circle shape inside a container.
The registration and origin will be the center.
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var circle = new Circle(50, "red").center();
// or with 10 pixel grey stroke
var circle = new Circle(50, "red", "#666", 10).center();
// change the color of the circle to a radial gradient fill
circle.color = new RadialColor([yellow,green], [0, .7], 0, 0, 20, 0, 0, 50);
// make a half circle - or any percent of a circle
var semi = new Circle({radius:200, color:pink, percent:50}).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
radius - |ZIM VEE| (default 50) the radius (from the center to the edge or half the diameter) ;-)
color - |ZIM VEE| (default "black") the fill color as any CSS color including "rgba()" for alpha fill (set a to 0 for tranparent fill)
borderColor - |ZIM VEE| (default null) the stroke color
borderWidth - |ZIM VEE| (default 1 if stroke is set) the size of the stroke in pixels
dashed - (default false) set to true for dashed border (if borderWidth or borderColor set)
or set to an array of line size then space size, etc.
eg. [20, 10] is 20 line and 10 space repeated and [20,100,50,10] is 20 line, 100 space, 50 line, 10 space, etc.
percent - (default 100) set to a percentage of a circle (arc) - registration stays at radius center, bounds shrink to arc
percentClose - (default true) set to false to not close the border of a circle with percent set
strokeObj - (default {caps:"butt", joints:"miter", miterLimit:10, ignoreScale:false}) set to adjust stroke properties
// note, not all applicable to a Circle - perhaps just ignoreScale...
caps options: "butt", "round", "square" or 0,1,2
joints options: "miter", "round", "bevel" or 0,1,2
miterLimit is the ration at which the mitered joint will be clipped
ignoreScale set to true will draw the specified line thickness regardless of object scale
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact) - makes a copy of the shape
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
cloneAll(exact, style, group, inherit) - copies shape and any custom content in shape - experimental - usually shapes do not have content (use a Container)
exact (default false) in theory will copy ZIM VEE values as they are in the original
see main class for style, group, inherit parameters
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
shape - gives access to the circle shape
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1, 5) will wiggle the colorRange
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
depreciated - see ZIM GradientColor, RadialColor and BitmapColor
borderColor - get and set the stroke color
borderColorCommand - access to the CreateJS stroke command for bitmap, linearGradient and radialGradient strokes
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Stroke.html
borderWidth - get and set the stroke size in pixels
borderWidthCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
dashed - get and set the dashed - use true / false or an array (see dashed parameter)
dashedOffset - get and set the offset of the dash (50 default) - can animate this property for a marquee effect
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
radius - gets or sets the radius.
The radius is independent of scaling and can be different than the width/2
Setting the radius redraws the circle but any current scaling is kept
percent - get or set the percent of the circle (see percent parameter)
percentClose - get or set the percent close of the circle (see percentClose parameter)
mouseChildren - set to false to avoid dragging the shape inside
to drag or interact with objects inside then set mouseChildren to true
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+51
zim.Circle = function(radius, color, borderColor, borderWidth, dashed, percent, percentClose, strokeObj, style, group, inherit) {
var sig = "radius, color, borderColor, borderWidth, dashed, percent, percentClose, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Circle, arguments, sig, this)) return duo;
z_d("51");
this.zimCustomShape_constructor(null,null,null,null,false);
this.type = "Circle";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(radius)) radius = DS.radius!=null?DS.radius:50;
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(percent)) percent = DS.percent!=null?DS.percent:100;
if (zot(percentClose)) percentClose = DS.percentClose!=null?DS.percentClose:true;
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
// PICK
var oa = remember(radius, color, borderColor, borderWidth, percent);
function remember() {return arguments;} // for cloning PICK
radius = zim.Pick.choose(radius);
color = zim.Pick.choose(color);
borderColor = zim.Pick.choose(borderColor);
borderWidth = zim.Pick.choose(borderWidth);
percent = zim.Pick.choose(percent);
var that = this;
that._radius = radius;
that._color = color;
that._borderColor = borderColor;
that._borderWidth = borderWidth;
that._dashed = dashed;
if (that._dashed && !Array.isArray(that._dashed)) that._dashed = [10, 10];
var circle = this.shape = new createjs.Shape();
this.addChild(circle);
var g = circle.graphics;
that.drawShape = function() {
g.c();
that.colorCommand = g.f(that._color).command;
if (that._color && that._color.type) that.specialColor(that.colorCommand, that._color);
// border of 0 or a string value still draws a border in CreateJS
if (zot(that._borderWidth) || that._borderWidth > 0) { // no border specified or a border > 0
if (!zot(that._borderColor) || !zot(that._borderWidth)) { // either a border color or thickness
if (zot(that._borderColor)) that._borderColor = "black";
that.borderColorCommand = g.s(that._borderColor).command;
if (that._borderColor && that._borderColor.type) that.specialColor(that.borderColorCommand, that._borderColor);
that.borderWidthCommand = g.ss(that._borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (that._dashed) that.borderDashedCommand = g.sd(Array.isArray(that._dashed)?that._dashed:[10, 10], that._dashedOffset).command;
}
}
var h = that._radius*2;
if (typeof percent == "number" && percent >= 0 && percent < 100) {
var p = 360*percent/100/2;
g.arc(0, 0, that._radius, (-p-90)*Math.PI/180, (p-90)*Math.PI/180, false);
if (percentClose) g.cp();
h = that._radius-Math.cos(p*Math.PI/180)*that._radius;
} else {
g.dc(0,0,that._radius);
}
that.setBounds(-that._radius,-that._radius,that._radius*2,h);
};
that.drawShape();
Object.defineProperty(that, 'radius', {
get: function() {
return that._radius;
},
set: function(value) {
that._radius = value;
that.drawShape();
}
});
Object.defineProperty(that, 'percent', {
get: function() {
return percent;
},
set: function(value) {
percent = value;
that.drawShape();
}
});
Object.defineProperty(that, 'percentClose', {
get: function() {
return percentClose;
},
set: function(value) {
percentClose = value;
that.drawShape();
}
});
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NOTE: extends ZIM CustomShape for more properties and a few functions.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function(exact, container) {
var newShape = that.cloneProps(new zim.Circle((exact||!zim.isPick(oa[0]))?that.radius:oa[0], (exact||!zim.isPick(oa[1]))?that.color:oa[1], (exact||!zim.isPick(oa[2]))?that.borderColor:oa[2], (exact||!zim.isPick(oa[3]))?that.borderWidth:oa[3], that.dashed, (exact||!zim.isPick(oa[4]))?percent:oa[4], percentClose, strokeObj, style, this.group, inherit));
if (that.linearGradientParams) newShape.linearGradient.apply(newShape, that.linearGradientParams);
if (that.radialGradientParams) newShape.radialGradient.apply(newShape, that.radialGradientParams);
return newShape;
};
};
zim.extend(zim.Circle, zim.CustomShape, "clone", "zimCustomShape", false);
//-51
/*--
zim.Rectangle = function(width, height, color, borderColor, borderWidth, corner, dashed, strokeObj, style, group, inherit)
Rectangle
zim class - extends a zim.CustomShape which extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a rectangle shape inside a container.
The registration and origin will be top left corner.
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var rect = new Rectangle(200, 100, "blue").center();
// or with rounded corners:
var rect = new Rectangle({width:200, height:100, color:"blue", corner:20}).center();;
// or with 2 pixel white stroke
var rect = new Rectangle(200, 100, "blue", "white", 2).center();;
// fill the rectangle with a Bitmap fill assuming icon has been loaded - not the image property
var rect = new Rectangle(200, 300, new BitmapColor(asset("icon.png"))).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - |ZIM VEE| (default the height if provided else 100) the width
height - |ZIM VEE| (default the width if provided else 100) the height
color - |ZIM VEE| (default "black") the fill color as any CSS color including "rgba()" for alpha fill (set a to 0 for tranparent fill)
borderColor - |ZIM VEE| (default null) the stroke color
borderWidth - |ZIM VEE| (default 1 if stroke is set) the size of the stroke in pixels
corner - (default 0) the round of corner
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
dashed - (default false) set to true for dashed border (if borderWidth or borderColor set)
or set to an array of line size then space size, etc.
eg. [20, 10] is 20 line and 10 space repeated and [20,100,50,10] is 20 line, 100 space, 50 line, 10 space, etc.
strokeObj - (default {caps:"butt", joints:"miter", miterLimit:10, ignoreScale:false}) set to adjust stroke properties
caps options: "butt", "round", "square" or 0,1,2
joints options: "miter", "round", "bevel" or 0,1,2
miterLimit is the ration at which the mitered joint will be clipped
ignoreScale set to true will draw the specified line thickness regardless of object scale
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact) - makes a copy of the shape
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
cloneAll(exact style, group, inherit) - copies shape and any custom content in shape - experimental - usually shapes do not have content (use a Container)
exact (default false) in theory will copy ZIM VEE values as they are in the original
see main class for style, group, inherit parameters
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
shape - gives access to the rectangle shape
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1, 5) will wiggle the colorRange
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
depreciated - see ZIM GradientColor, RadialColor and BitmapColor
borderColor - get and set the stroke color
borderColorCommand - access to the CreateJS stroke command for bitmap, linearGradient and radialGradient strokes
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Stroke.html
borderWidth - get and set the stroke size in pixels
borderWidthCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
corner - get or set the corner or array of corners (see corner parameter)
dashed - get and set the dashed - use true / false or an array (see dashed parameter)
dashedOffset - get and set the offset of the dash (50 default) - can animate this property for a marquee effect
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
mouseChildren - set to false to avoid dragging the shape inside
to drag or interact with objects inside then set mouseChildren to true
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+52
zim.Rectangle = function(width, height, color, borderColor, borderWidth, corner, dashed, strokeObj, style, group, inherit) {
var sig = "width, height, color, borderColor, borderWidth, corner, dashed, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Rectangle, arguments, sig, this)) return duo;
z_d("52");
this.zimCustomShape_constructor(null,null,null,null,false);
this.type = "Rectangle";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:null;
if (zot(height)) height = DS.height!=null?DS.height:!zot(width)?width:100;
if (zot(width)) width = height;
if (zot(corner)) corner = DS.corner!=null?DS.corner:0;
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
// PICK
var oa = remember(width, height, color, borderColor, borderWidth);
function remember() {return arguments;} // for cloning PICK
width = zim.Pick.choose(width);
height = zim.Pick.choose(height);
color = zim.Pick.choose(color);
borderColor = zim.Pick.choose(borderColor);
borderWidth = zim.Pick.choose(borderWidth);
var that = this;
that._color = color;
that._borderColor = borderColor;
that._borderWidth = borderWidth;
that._dashed = dashed;
if (that._dashed && !Array.isArray(that._dashed)) that._dashed = [10, 10];
that._corner = corner;
var rectangle = this.shape = new createjs.Shape();
this.addChild(rectangle);
var g = rectangle.graphics;
that.drawShape = function() {
g.c();
that.colorCommand = g.f(that._color).command;
if (color && color.type) that.specialColor(that.colorCommand, color);
// border of 0 or a string value still draws a border in CreateJS
if (zot(that._borderWidth) || that._borderWidth > 0) { // no border specified or a border > 0
if (!zot(that._borderColor) || !zot(that._borderWidth)) { // either a border color or thickness
if (zot(that._borderColor)) that._borderColor = "black";
that.borderColorCommand = g.s(that._borderColor).command;
if (that._borderColor && that._borderColor.type) that.specialColor(that.borderColorCommand, that._borderColor);
that.borderWidthCommand = g.ss(that._borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (that._dashed) that.borderDashedCommand = g.sd(Array.isArray(that._dashed)?that._dashed:[10, 10], that._dashedOffset).command;
}
}
if (Array.isArray(that._corner)) {
g.rc(0,0,width,height,that._corner[0],that._corner[1],that._corner[2],that._corner[3]);
} else if (that._corner > 0) {
g.rr(0,0,width,height,that._corner);
} else {
g.r(0,0,width,height);
}
that.setBounds(0,0,width,height);
};
that.drawShape();
// Object.defineProperty(that, 'corner', {
// get: function() {
// return corner;
// },
// set: function(value) {
// corner = value;
// that.drawShape();
// }
// });
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NOTE: extends ZIM CustomShape for more properties and a few functions.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function(exact) {
var newShape = that.cloneProps(new zim.Rectangle((exact||!zim.isPick(oa[0]))?width:oa[0], (exact||!zim.isPick(oa[1]))?height:oa[1], (exact||!zim.isPick(oa[2]))?that.color:oa[2], (exact||!zim.isPick(oa[3]))?that.borderColor:oa[3], (exact||!zim.isPick(oa[4]))?that.borderWidth:oa[4], corner, that._dashed, strokeObj, style, this.group, inherit));
return newShape;
};
};
zim.extend(zim.Rectangle, zim.CustomShape, "clone", "zimCustomShape", false);
//-52
/*--
zim.Triangle = function(a, b, c, color, borderColor, borderWidth, corner, center, adjust, dashed, strokeObj, style, group, inherit)
Triangle
zim class - extends a zim.CustomShape which extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a triangle shape inside a container using three line lengths.
Passing one length parameter makes an equilateral triangle.
Passing two length parameters makes an isosceles triangle.
Passing -1 as the last length parameter makes a 90 degree triangle.
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var tri = new Triangle(200, null, null, "green").center();
// all three sides specified - tall pointy triangle with yellow stroke of 10 pixels
var tri = new Triangle(100, 200, 200, "green", "yellow", 10).center();
// here we adjust so rotation looks better
var tri = new Triangle({a:200, color:"green", adjust:30})
.center()
.animate({obj:{rotation:360}, time:3, ease:"linear", loop:true});
// here we fill the triangle with a linear gradient color
tri.color = new GradientColor([green, blue ,green], [.2, .5, .8], 0, 0, tri.width, 0);
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
a, b and c - |ZIM VEE| (default 100) the lengths of the sides
a will run horizontally along the bottom
b is upwards and c is back to the origin
if c is set to -1 will assume a 90 angle
color - |ZIM VEE| (default "black") the fill color as any CSS color including "rgba()" for alpha fill (set a to 0 for tranparent fill)
borderColor - |ZIM VEE| (default null) the stroke color
borderWidth - |ZIM VEE| (default 1 if stroke is set) the size of the stroke in pixels
corner - (default 0) the round of corner
can also be an array of [bottomLeft, bottomRight, top]
center - (default true) puts the registration point to the center
adjust - (default 0) pixels to bring center towards vertical base
the actual center is not really the weighted center
dashed - (default false) set to true for dashed border (if borderWidth or borderColor set)
or set to an array of line size then space size, etc.
eg. [20, 10] is 20 line and 10 space repeated and [20,100,50,10] is 20 line, 100 space, 50 line, 10 space, etc.
strokeObj - (default {caps:"butt", joints:"miter", miterLimit:10, ignoreScale:false}) set to adjust stroke properties
caps options: "butt", "round", "square" or 0,1,2
joints options: "miter", "round", "bevel" or 0,1,2
miterLimit is the ration at which the mitered joint will be clipped
ignoreScale set to true will draw the specified line thickness regardless of object scale
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy of the shape
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
cloneAll(exact style, group, inherit) - copies shape and any custom content in shape - experimental - usually shapes do not have content (use a Container)
exact (default false) in theory will copy ZIM VEE values as they are in the original
see main class for style, group, inherit parameters
exact (default false) in theory will copy ZIM VEE values as they are in the original
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
shape - gives access to the triangle shape
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1, 5) will wiggle the colorRange
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
depreciated - see ZIM GradientColor, RadialColor and BitmapColor
borderColor - get and set the stroke color
borderColorCommand - access to the CreateJS stroke command for bitmap, linearGradient and radialGradient strokes
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Stroke.html
borderWidth - get and set the stroke size in pixels
borderWidthCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
corner - get or set the corner or array of corners (see corner parameter)
dashed - get and set the dashed - use true / false or an array (see dashed parameter)
dashedOffset - get and set the offset of the dash (50 default) - can animate this property for a marquee effect
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
one, two, three - read only - points with x, y properties for bottom left, bottom right, top right
angles - read only - Array of angles [bottom left, bottom right, top right]
adjusted - read only - the value of the adjust parameter or 0 if no adjust was supplied
mouseChildren - set to false to avoid dragging the shape inside
to drag or interact with objects inside then set mouseChildren to true
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+53
zim.Triangle = function(a, b, c, color, borderColor, borderWidth, corner, center, adjust, dashed, strokeObj, style, group, inherit) {
var sig = "a, b, c, color, borderColor, borderWidth, corner, center, adjust, dashed, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Triangle, arguments, sig, this)) return duo;
z_d("53");
this.zimCustomShape_constructor(null,null,null,null,false);
this.type = "Triangle";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(a)) a = DS.a!=null?DS.a:100;
if (zot(b)) b = DS.b!=null?DS.b:a;
if (zot(c)) c = DS.c!=null?DS.c:b;
if (c==-1) c = Math.sqrt(Math.pow(a,2)+Math.pow(b,2));
if (zot(corner)) corner = DS.corner!=null?DS.corner:0;
if (zot(center)) center = DS.center!=null?DS.center:true;
if (zot(adjust)) adjust = DS.adjust!=null?DS.adjust:0;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(adjust)) adjust = DS.adjust!=null?DS.adjust:0;
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
// PICK
var oa = remember(a, b, c, color, borderColor, borderWidth);
function remember() {return arguments;} // for cloning PICK
a = zim.Pick.choose(a);
b = zim.Pick.choose(b);
c = zim.Pick.choose(c);
this.a = a;
this.b = b;
this.c = c;
color = zim.Pick.choose(color);
borderColor = zim.Pick.choose(borderColor);
borderWidth = zim.Pick.choose(borderWidth);
var that = this;
that._color = color;
that._borderColor = borderColor;
that._borderWidth = borderWidth;
that._dashed = dashed;
if (that._dashed && !Array.isArray(that._dashed)) that._dashed = [10, 10];
that._corner = corner;
var lines = [a,b,c];
lines.sort(function(a, b){return b-a;});
var aa = lines[0];
var bb = lines[1];
var cc = lines[2];
var order = [lines.indexOf(a), lines.indexOf(b), lines.indexOf(c)];
if (aa > bb+cc) {
zog("zim display - Triangle(): invalid triangle lengths");
return;
}
var tri = this.shape = new createjs.Shape();
this.adjusted = adjust;
this.addChild(tri);
var g = tri.graphics;
that.drawShape = function() {
var corners = [];
if (Array.isArray(that._corner)) corners = that._corner;
else corners.push(that._corner, that._corner, that._corner);
for(var i=0; i<3; i++) {
if (corner[i] < 0 || typeof corner[i] != "number") corner[i] = 0;
}
g.c();
that.colorCommand = g.f(that._color).command;
if (that._color && that._color.type) that.specialColor(that.colorCommand, that._color);
// border of 0 or a string value still draws a border in CreateJS
if (zot(that._borderWidth) || that._borderWidth > 0) { // no border specified or a border > 0
if (!zot(that._borderColor) || !zot(that._borderWidth)) { // either a border color or thickness
if (zot(that._borderColor)) that._borderColor = "black";
that.borderColorCommand = g.s(that._borderColor).command;
if (that._borderColor && that._borderColor.type) that.specialColor(that.borderColorCommand, that._borderColor);
that.borderWidthCommand = g.ss(that._borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (that._dashed) that.borderDashedCommand = g.sd(Array.isArray(that._dashed)?that._dashed:[10, 10], that._dashedOffset).command;
}
}
// g.mt(5,100)
// g.at(100,100, 0,0, 15).at(0,0, 0,100, 5).at(0,100,100,100, 5)
that.one={x:0,y:0};
that.two={x:a,y:0};
// find biggest angle with cosine rule
var angle1 = Math.acos( (Math.pow(bb,2) + Math.pow(cc,2) - Math.pow(aa,2)) / (2 * bb * cc) ) * 180 / Math.PI;
// use the sine rule for next biggest angle
var angle2 = Math.asin( bb * Math.sin(angle1 * Math.PI / 180) / aa ) * 180 / Math.PI;
// find last angle
var angle3 = 180 - angle1 - angle2;
// get position of angles by mapping to opposite side sizes
// as in smallest angle is across from smallest side
// largest angle is across from largest size, etc.
var temp = [angle1, angle2, angle3]; // largets to smallest
that.angles = [temp[order[1]], temp[order[2]], temp[order[0]]];
var nextAngle = that.angles[1];
var backX = Math.cos(nextAngle * Math.PI / 180) * b;
var upY = Math.sin(nextAngle * Math.PI / 180) * b;
var width = Math.max(a, a-backX);
var height = upY;
that.setBounds(0,adjust,width,height);
tri.y = height;
that.three={x:a-backX,y:0-upY};
var sX = a*corners[0]/((corners[0]+corners[1])||1);
g
.mt(sX,0)
.at(a,0, a-backX,0-upY, corners[1])
.at(a-backX,0-upY, 0,0, corners[2])
.at(0,0, a,0, corners[0])
.lt(sX,0);
g.cp();
if (center) {
that.regX = width/2;
that.regY = height/2;
}
if (adjust) {
that.shape.y+=adjust;
}
};
that.drawShape();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NOTE: extends ZIM CustomShape for more properties and a few functions.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function(exact) {
var newShape = that.cloneProps(new zim.Triangle((exact||!zim.isPick(oa[0]))?a:oa[0], (exact||!zim.isPick(oa[1]))?b:oa[1], (exact||!zim.isPick(oa[2]))?c:oa[2], (exact||!zim.isPick(oa[3]))?that.color:oa[3], (exact||!zim.isPick(oa[4]))?that.borderColor:oa[4], (exact||!zim.isPick(oa[5]))?that.borderWidth:oa[5], corner, center, adjust, dashed, strokeObj, style, this.group, inherit));
if (that.linearGradientParams) newShape.linearGradient.apply(newShape, that.linearGradientParams);
if (that.radialGradientParams) newShape.radialGradient.apply(newShape, that.radialGradientParams);
return newShape;
};
};
zim.extend(zim.Triangle, zim.CustomShape, "clone", "zimCustomShape");
//-53
/*--
zim.Poly = function(radius, sides, pointSize, color, borderColor, borderWidth, dashed, strokeObj, style, group, inherit)
Poly
zim class - extends a zim.CustomShape which extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a regular polygon with radius like a Circle.
The number of sides can be set as well as a pointSize that will make star-like shapes
The registration and origin will be the center.
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var poly = new Poly(200, 5, 0, pink).center(); // pentagon
var poly = new Poly(200, 5, .6, pink).center(); // five point star
new Poly(200, 8, 2.5, purple)
.sca(1.1).center().sha("rgba(0,0,0,.3)", 10,10,5); // backing...
new Poly(200, 8, 2.5, pink)
.center();
new Label({text:"P O L Y", color:green, font:"impact", outlineColor:blue, size:75, shiftVertical:10})
.sha().rot(-25).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
radius - |ZIM VEE| (default 50) the radius (from the center to the edge or half the diameter) ;-)
sides - |ZIM VEE| (default 5) the number of sides
pointSize - |ZIM VEE| (default 0) a factor that will indent or outdent the sides to form stars
0 is no indent - 1 is a complete indent - which will have no fill and if there is a border will look like a stick figure
beyond 1 is cool - it overlaps on itself and makes multiple patterns
color - |ZIM VEE| (default "black") the fill color as any CSS color including "rgba()" for alpha fill (set a to 0 for tranparent fill)
borderColor - |ZIM VEE| (default null) the stroke color
borderWidth - |ZIM VEE| (default 1 if stroke is set) the size of the stroke in pixels
dashed - (default false) set to true for dashed border (if borderWidth or borderColor set)
or set to an array of line size then space size, etc.
eg. [20, 10] is 20 line and 10 space repeated and [20,100,50,10] is 20 line, 100 space, 50 line, 10 space, etc.
strokeObj - (default {caps:"butt", joints:"miter", miterLimit:10, ignoreScale:false}) set to adjust stroke properties
caps options: "butt", "round", "square" or 0,1,2
joints options: "miter", "round", "bevel" or 0,1,2
miterLimit is the ration at which the mitered joint will be clipped
ignoreScale set to true will draw the specified line thickness regardless of object scale
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact) - makes a copy of the shape
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
cloneAll(exact style, group, inherit) - copies shape and any custom content in shape - experimental - usually shapes do not have content (use a Container)
exact (default false) in theory will copy ZIM VEE values as they are in the original
see main class for style, group, inherit parameters
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
radius - gets or sets the radius.
The radius is independent of scaling and can be different than the width/2
Setting the radius redraws the circle but any current scaling is kept
sides - get or set the sides of the shape
pointSize - get or set the point size of the shape (can be animated too)
shape - gives access to the poly shape
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1, 5) will wiggle the colorRange
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
depreciated - see ZIM GradientColor, RadialColor and BitmapColor
borderColor - get and set the stroke color
borderColorCommand - access to the CreateJS stroke command for bitmap, linearGradient and radialGradient strokes
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Stroke.html
borderWidth - get and set the stroke size in pixels
borderWidthCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
dashed - get and set the dashed - use true / false or an array (see dashed parameter)
dashedOffset - get and set the offset of the dash (50 default) - can animate this property for a marquee effect
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
mouseChildren - set to false to avoid dragging the shape inside
to drag or interact with objects inside then set mouseChildren to true
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+53.1
zim.Poly = function(radius, sides, pointSize, color, borderColor, borderWidth, dashed, strokeObj, style, group, inherit) {
var sig = "radius, sides, pointSize, color, borderColor, borderWidth, dashed, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Poly, arguments, sig, this)) return duo;
z_d("53.1");
this.zimCustomShape_constructor(null,null,null,null,false);
this.type = "Poly";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(radius)) radius = DS.radius!=null?DS.radius:50;
if (zot(sides)) sides = DS.sides!=null?DS.sides:5;
if (zot(pointSize)) pointSize = DS.pointSize!=null?DS.pointSize:0;
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
// PICK
var oa = remember(radius, sides, pointSize, color, borderColor, borderWidth);
function remember() {return arguments;} // for cloning PICK
radius = zim.Pick.choose(radius);
sides = zim.Pick.choose(sides);
pointSize = zim.Pick.choose(pointSize);
color = zim.Pick.choose(color);
borderColor = zim.Pick.choose(borderColor);
borderWidth = zim.Pick.choose(borderWidth);
var that = this;
that._radius = radius;
that._color = color;
that._sides = sides;
that._pointSize = pointSize;
that._borderColor = borderColor;
that._borderWidth = borderWidth;
that._dashed = dashed;
if (that._dashed && !Array.isArray(that._dashed)) that._dashed = [10, 10];
var poly = this.shape = new createjs.Shape();
this.addChild(poly);
poly.rotation = -90;
var g = poly.graphics;
that.drawShape = function() {
g.c();
that.colorCommand = g.f(that._color).command;
if (that._color && that._color.type) that.specialColor(that.colorCommand, that._color);
// border of 0 or a string value still draws a border in CreateJS
if (zot(that._borderWidth) || that._borderWidth > 0) { // no border specified or a border > 0
if (!zot(that._borderColor) || !zot(that._borderWidth)) { // either a border color or thickness
if (zot(that._borderColor)) that._borderColor = "black";
that.borderColorCommand = g.s(that._borderColor).command;
if (that._borderColor && that._borderColor.type) that.specialColor(that.borderColorCommand, that._borderColor);
that.borderWidthCommand = g.ss(that._borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (that._dashed) that.borderDashedCommand = g.sd(Array.isArray(that._dashed)?that._dashed:[10, 10], that._dashedOffset).command;
}
}
g.dp(0,0,that._radius, that._sides, that._pointSize);
that.setBounds(-that._radius,-that._radius, that._radius*2, that._radius*2);
};
that.drawShape();
Object.defineProperty(that, 'radius', {
get: function() {
return that._radius;
},
set: function(value) {
that._radius = value;
that.drawShape();
}
});
Object.defineProperty(that, 'sides', {
get: function() {
return that._sides;
},
set: function(value) {
that._sides = value;
that.drawShape();
}
});
Object.defineProperty(that, 'pointSize', {
get: function() {
return that._pointSize;
},
set: function(value) {
that._pointSize = value;
that.drawShape();
}
});
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NOTE: extends ZIM CustomShape for more properties and a few functions.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function(exact, container) {
var newShape = that.cloneProps(new zim.Poly((exact||!zim.isPick(oa[0]))?that.radius:oa[0], (exact||!zim.isPick(oa[1]))?that.sides:oa[1], (exact||!zim.isPick(oa[2]))?that.pointSize:oa[2], (exact||!zim.isPick(oa[3]))?that.color:oa[3], (exact||!zim.isPick(oa[4]))?that.borderColor:oa[4], (exact||!zim.isPick(oa[5]))?that.borderWidth:oa[5], that.dashed, strokeObj, style, this.group, inherit));
if (that.linearGradientParams) newShape.linearGradient.apply(newShape, that.linearGradientParams);
if (that.radialGradientParams) newShape.radialGradient.apply(newShape, that.radialGradientParams);
return newShape;
};
};
zim.extend(zim.Poly, zim.CustomShape, "clone", "zimCustomShape", false);
//-53.1
/*--
zim.Line = function(length, thickness, color, startHead, endHead, dashed, strokeObj, lineType, lineOrientation, curveH, curveV, points, style, group, inherit)
Line
zim class - extends a zim.CustomShape which extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a straight line with a length and thickness.
See also ZIM Squiggle() with points:[[0,0], [100,0] for instance for Bezier handles, etc.
See also ZIM Shape() for custom lines, curves, etc.
The registration and origin will be at the start point at the left.
Start point and end point can be adjusted in various ways to accommodate animation, etc.
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var line = new Line(500).center(); // centered line
END EXAMPLE
EXAMPLE
var line = new Line({points:[[0,0],[100,0],[100,100],[200,100]]}).center(); // over, up, over, etc.
// or with quadratic curves:
// 100,0 is control point to x,y of 100,50
var line = new Line({points:[[0,0],[100,0,100,50],[100,100,200,100]]}).center(); // over, up, over
// or with bezier curves:
// 100,0 is first control point, 100,0 is second control point and 100,50 is final point
var line = new Line({points:[[0,0],[100,0,100,0,100,50],[100,100,100,100,200,100]]}).center(); // over, up, over
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
length - |ZIM VEE| (default 100) the length of the line - see also length property and start and end point properties
thickness - |ZIM VEE| (default 3) the size of the stroke in pixels
color - |ZIM VEE| (default "black") the fill color as any CSS color including "rgba()" for alpha fill (set a to 0 for tranparent fill)
startHead - |ZIM VEE| (default "none") the start head of the line - set to "arrow" (or "triangle") or "circle" or a custom DisplayObject - probably centerReg this
endHead - |ZIM VEE| (default "none") the end head of the line - set to "arrow" (or "triangle") or "circle" or a custom DisplayObject - probably centerReg this
dashed - (default false) set to true for dashed border (if borderWidth or borderColor set)
or set to an array of line size then space size, etc.
eg. [20, 10] is 20 line and 10 space repeated and [20,100,50,10] is 20 line, 100 space, 50 line, 10 space, etc.
strokeObj - (default {caps:"butt", joints:"miter", miterLimit:10, ignoreScale:false}) set to adjust stroke properties
caps options: "butt", "round", "square" or 0,1,2
joints options: "miter", "round", "bevel" or 0,1,2
miterLimit is the ration at which the mitered joint will be clipped
ignoreScale set to true will draw the specified line thickness regardless of object scale
lineType - (default "straight") - by default the line is a straight line between points
set to "corner" to draw only horizontal and vertical lines at 90 degree angles between lines (see lineOrientation)
set to "curve" to draw horizontal and vertical lines with curves between lines (see lineOrientation)
lineOrientation - (default "auto") - for lineType other than straight automatically decide between horizontal or vertical
set to "horizontal" to draw two horizontal lines and one vertical line between points
set to "vertical" to draw two vertical lines and one horizontal line between points
curveH - (default 100) - for "curve" lineType this is the horizontal distance of the curve
curveV - (default 100) - for "curve" lineType this is the vertical distance of the curve
points - (default null) an Array of points for the line which will ignore length and lineType parameters
points in the array can have the following formats (a mix is okay too):
[x,y] points for straight lines. This format should also be used for first point
[cpX, cpY, x, y] for quadratic curve to with a single control point followed by the destination point
[cp1X, cp1Y, cp2X, cp2Y, x, y] for Bezier curve to with start and end control points followed by the destination point
// see the ZIM Shape docs (or https://www.createjs.com/docs/easeljs/classes/Graphics) for details on the curves
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setPoints(a, b, c, d) - pass in two ZIM Points or four numbers to set start points and end points or an array of points
this will not change the x and y of the shape
also see startPoint, endPoint, startX, startY, endX, endY properties
if an array is used the points are remade like when made with the points parameter
from(a, b) - pass in a ZIM Point or two numbers to set the start point
to(a, b) - pass in a ZIM Point or two numbers to set the end point
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact) - makes a copy of the shape
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
cloneAll(exact style, group, inherit) - copies shape and any custom content in shape - experimental - usually shapes do not have content (use a Container)
exact (default false) in theory will copy ZIM VEE values as they are in the original
see main class for style, group, inherit parameters
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
** below will not change the x and y of the shape
** if points is being used: length, startPoint, start and end X and Y, endPoint and angle are ignored - use the point property
length - gets or sets the length of the line - will grow from its registration point
startPoint - (ZIM Point or x,y object) get or set the start point
startX - get or set the start x point - allows for animation
startY - get or set the start y point - allows for animation
endPoint - (ZIM Point or x,y object) get or set the end point
endX - get or set the end x point - allows for animation
endY - get or set the end y point - allows for animation
startHead - get or set the start head - see startHead parameter
endHead - get or set the end head - see endHead parameter
angle - gets (not sets) the current angle relative to the line (does not include line rotation)
points - get and set the points array (see points parameter) - ignoring all settings above
** above will not change the x and y of the shape
shape - gives access to the line shape
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1, 5) will wiggle the colorRange
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
depreciated - see ZIM GradientColor, RadialColor and BitmapColor
thickness - get and set the stroke size in pixels
thicknessCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
dashed - get and set the dashed - use true / false or an array (see dashed parameter)
dashedOffset - get and set the offset of the dash (50 default) - can animate this property for a marquee effect
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
lineType - read only access to type of line "straight", "corner", "curve"
mouseChildren - set to false to avoid dragging the shape inside
to drag or interact with objects inside then set mouseChildren to true
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+53.15
zim.Line = function(length, thickness, color, startHead, endHead, dashed, strokeObj, lineType, lineOrientation, curveH, curveV, points, style, group, inherit) {
var sig = "length, thickness, color, startHead, endHead, dashed, strokeObj, lineType, lineOrientation, curveH, curveV, points, style, group, inherit";
var duo; if (duo = zob(zim.Line, arguments, sig, this)) return duo;
z_d("53.15");
this.zimCustomShape_constructor(null,null,null,null,false);
this.type = "Line";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(length)) length = DS.length!=null?DS.length:100;
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(thickness)) thickness = DS.thickness!=null?DS.thickness:3;
if (zot(color)) color = DS.color!=null?DS.color:"black";
if (zot(startHead)) startHead = DS.startHead!=null?DS.startHead:null;
if (zot(endHead)) endHead = DS.endHead!=null?DS.endHead:null;
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
if (zot(lineType)) lineType = DS.lineType!=null?DS.lineType:"straight";
if (lineType !== "corner" && lineType != "curve") lineType = "straight";
if (zot(lineOrientation)) lineOrientation = DS.lineOrientation!=null?DS.lineOrientation:"auto";
if (lineOrientation !== "vertical" && lineOrientation != "horizontal") lineOrientation = "auto";
if (zot(curveH)) curveH = DS.curveH!=null?DS.curveH:20;
if (zot(curveV)) curveV = DS.curveV!=null?DS.curveV:20;
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
// PICK
var oa = remember(length, color, thickness, startHead, endHead);
function remember() {return arguments;} // for cloning PICK
length = zim.Pick.choose(length);
color = zim.Pick.choose(color);
thickness = zim.Pick.choose(thickness);
startHead = zim.Pick.choose(startHead);
endHead = zim.Pick.choose(endHead);
// do below otherwise will be the same head and get moved if cloned
if (startHead && startHead.clone) startHead = startHead.clone();
if (endHead && endHead.clone) endHead = endHead.clone();
var that = this;
that._length = length;
that._color = color;
that._thickness = thickness;
that._dashed = dashed;
if (that._dashed && !Array.isArray(that._dashed)) that._dashed = [10, 10];
that._startX = 0;
that._startY = 0;
that._endX = length;
that._endY = 0;
that._startHead = startHead;
that._endHead = endHead;
that._points = points;
that._lineOrientation = lineOrientation;
that.angle = 0;
that.lineType = lineType;
var startRegY;
if (that._startHead) prepareHead("start", that._startHead);
if (that._endHead) prepareHead("end", that._endHead);
function prepareHead(type, head) {
if (head == "triangle" || head == "arrow") {
var h = that["_"+type+"Head"] = new zim.Triangle(thickness*4, thickness*4, thickness*4, color);
h.rotation = 90;
} else if (head == "circle") {
that["_"+type+"Head"] = new zim.Circle(thickness*2.2, color);
}
if (zot(that["_"+type+"Head"].startAngle)) that["_"+type+"Head"].startAngle = that["_"+type+"Head"].rotation;
}
startHead = that._startHead;
endHead = that._endHead;
if (startHead && startHead.type == "Triangle") startHead.startRegY = startHead.regY;
if (endHead && endHead.type == "Triangle") endHead.startRegY = endHead.regY;
var shape = this.shape = new createjs.Shape();
this.addChild(shape);
var g = shape.graphics;
that.drawShape = function(arrowAdjustStart, arrowAdjustEnd) {
g.c();
that.colorCommand = g.s(that._color).command;
if (color && color.type) that.specialColor(that.colorCommand, color);
that.thicknessCommand = g.ss(that._thickness, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (that._dashed) {
that.dashedCommand = g.sd(Array.isArray(that._dashed)?that._dashed:[10, 10], that._dashedOffset).command;
}
var startArrowGuide;
var endArrowGuide;
if (that._points) {
var start = that._points[0];
that._startX = start[0];
that._startY = start[1];
var endPoint = that._points[that._points.length-1];
var end = [endPoint[endPoint.length-2], endPoint[endPoint.length-1]];
that._endX = end[0];
that._endY = end[1];
g.mt(start[0], start[1]);
for (var i=1; i= 4) { // last point in loop
endArrowGuide = [point[point.length-4], point[point.length-3], that._endX, that._endY];
} else {
var penPoint = that._points[that._points.length-2];
endArrowGuide = [penPoint[penPoint.lenth-2], penPoint[penPoint.lenth-1], that._endX, that._endY];
}
} else {
var sX = that._startX;
var sY = that._startY;
var eX = that._endX;
var eY = that._endY;
if (that.lineType == "straight") {
if (startHead && startHead.type == "Triangle") {
startHead.regY = 0;
var d = zim.dist(sX,sY,eX,eY);
if (d != 0) sX = sX + that._startHead.height/2*(eX-sX)/d;
if (d != 0) sY = sY + that._startHead.height/2*(eY-sY)/d;
}
if (endHead && endHead.type == "Triangle") {
endHead.regY = 0;
var d = zim.dist(sX,sY,eX,eY);
if (d != 0) eX = eX - that._endHead.height/2*(eX-sX)/d;
if (d != 0) eY = eY - that._endHead.height/2*(eY-sY)/d;
}
} else {
if (arrowAdjustStart) {
if (that._lineOrientation == "horizontal" || that.autoOrientation == "horizontal") {
if (startHead && startHead.type == "Triangle") {
startHead.regY = 0;
// if (eX > sX) sX += that._startHead.height/2;
// else sX -= that._startHead.height/2;
if (eX > sX) {
sX = Math.min(eX, sX+that._startHead.height/2);
} else {
sX = Math.max(eX, sX-that._startHead.height/2);
}
}
} else {
if (startHead && startHead.type == "Triangle") {
startHead.regY = 0;
// if (eY > sY) sY += that._startHead.height/2;
// else sY -= that._startHead.height/2;
if (eY > sY) {
sY = Math.min(eY, sY+that._startHead.height/2);
} else {
sY = Math.max(eY, sY-that._startHead.height/2);
}
}
}
} else {
if (startHead && startHead.type == "Triangle") startHead.regY = startHead.startRegY;
}
if (arrowAdjustEnd) {
if (that._lineOrientation == "horizontal" || that.autoOrientation == "horizontal") {
if (endHead && endHead.type == "Triangle") {
endHead.regY = 0;
if (eX > sX) eX -= that._endHead.height/2;
else eX += that._endHead.height/2;
}
} else {
if (endHead && endHead.type == "Triangle") {
endHead.regY = 0;
if (eY > sY) eY -= that._endHead.height/2;
else eY += that._endHead.height/2;
}
}
} else {
if (endHead && endHead.type == "Triangle") endHead.regY = endHead.startRegY;
}
}
if (that.lineType == "straight") {
g.mt(sX, sY).lt(eX, eY);
startArrowGuide = endArrowGuide = [sX, sY, eX, eY];
} else if (that.lineType == "corner") {
var midX = sX + (eX-sX)*.4;
var midY = sY + (eY-sY)*.4;
if (that._lineOrientation == "auto") {
that.autoOrientation = (Math.abs(sX-eX) > Math.abs(sY-eY))?"horizontal":"vertical";
}
if (that._lineOrientation == "horizontal" || that.autoOrientation == "horizontal") {
startArrowGuide = endArrowGuide = [sX, sY, midX, sY];
// startArrowGuide = endArrowGuide = [that._startX, that._startY, midX, that._startY];
g.mt(sX, sY).lt(midX, sY).lt(midX, eY).lt(eX, eY);
} else {
startArrowGuide = endArrowGuide = [sX, sY, sX, midY];
// startArrowGuide = endArrowGuide = [that._startX, that._startY, that._startX, midY];
g.mt(sX, sY).lt(sX, midY).lt(eX, midY).lt(eX, eY);
}
} else { // "curve"
var hSign = (sX > eX)?-1:1;
var vSign = (sY > eY)?-1:1;
var nextX = sX; // relative drawing would be handy but not implemente in version yet
var nextY = sY;
var distX = Math.abs(sX - eX);
var distY = Math.abs(sY - eY);
var curveX = Math.min(curveH, distX*.5); // need proportion curve until hits curveH
var curveY = Math.min(curveV, distY*.5);
if (that._lineOrientation == "auto") {
that.autoOrientation = (Math.abs(sX-eX) > Math.abs(sY-eY))?"horizontal":"vertical";
}
if (that._lineOrientation == "horizontal" || that.autoOrientation == "horizontal") {
var insideDistance = (distY-curveY*2);
var outsideDistance = (distX-curveX*2)/2;
g.mt(nextX, nextY);
if (outsideDistance > 0) {
nextX = nextX+outsideDistance*hSign;
g.lt(nextX, nextY);
}
var lastY = nextY;
nextY = nextY+curveY*vSign;
nextX = nextX+curveX*hSign;
g.qt(nextX, lastY, nextX, nextY);
startArrowGuide = endArrowGuide = [sX, sY, nextX, sY];
if (insideDistance > 0) {
nextY = nextY+insideDistance*vSign;
g.lt(nextX, nextY);
}
nextY = nextY+curveY*vSign;
var lastX = nextX;
nextX = nextX+curveX*hSign;
g.qt(lastX, nextY, nextX, nextY);
if (outsideDistance > 0) {
nextX = nextX+outsideDistance*hSign;
g.lt(nextX, nextY);
}
} else {
var insideDistance = (distX-curveX*2);
var outsideDistance = (distY-curveY*2)/2;
g.mt(nextX, nextY);
if (outsideDistance > 0) {
nextY = nextY+outsideDistance*vSign;
g.lt(nextX, nextY);
}
var lastX = nextX;
nextX = nextX+curveX*hSign;
nextY = nextY+curveY*vSign;
g.qt(lastX, nextY, nextX, nextY);
startArrowGuide = endArrowGuide = [sX, sY, sX, nextY];
if (insideDistance > 0) {
nextX = nextX+insideDistance*hSign;
g.lt(nextX, nextY);
}
nextX = nextX+curveX*hSign;
var lastY = nextY;
nextY = nextY+curveY*vSign;
g.qt(nextX, lastY, nextX, nextY);
if (outsideDistance > 0) {
nextY = nextY+outsideDistance*vSign;
g.lt(nextX, nextY);
}
}
}
}
that.setBounds(Math.min(that._startX, that._endX),Math.min(that._startY, that._endY),Math.abs(that._startX-that._endX),Math.abs(that._startY-that._endY));
that._length = Math.sqrt(Math.pow(that._startX-that._endX,2) + Math.pow(that._startY-that._endY,2));
that.angle = Math.atan2(that._endY-that._startY, that._endX-that._startX) * 180 / Math.PI;
if (that._startHead && that._startHead.loc) {
that._startHead.loc(that._startX, that._startY, that);
var startAngle = Math.atan2(startArrowGuide[3]-startArrowGuide[1], startArrowGuide[2]-startArrowGuide[0]) * 180 / Math.PI;
that._startHead.rotation = startAngle-180+that._startHead.startAngle;
}
if (that._endHead && that._endHead.loc) {
that._endHead.loc(that._endX, that._endY, that);
var endAngle = Math.atan2(endArrowGuide[3]-endArrowGuide[1], endArrowGuide[2]-endArrowGuide[0]) * 180 / Math.PI;
that._endHead.rotation = endAngle+that._endHead.startAngle;
}
};
that.drawShape();
this.setPoints = function(a, b, c, d, arrowAdjustStart, arrowAdjustEnd) {
if (Array.isArray(a) && zot(b)) {
that.points = a;
return that;
} else if (a && !zot(a.x)) {
that._startX = zot(a.x)?that._startX:a.x;
that._startY = zot(a.y)?that._startY:a.y;
if (b) {
that._endX = zot(b.x)?that._endX:b.x;
that._endY = zot(b.y)?that._endY:b.y;
}
} else {
that._startX = zot(a)?that._startX:a;
that._startY = zot(b)?that._startY:b;
that._endX = zot(c)?that._endX:c;
that._endY = zot(d)?that._endY:d;
}
that.drawShape(arrowAdjustStart, arrowAdjustEnd);
return that;
};
this.from = function(a, b) {
if (a && !zot(a.x)) {
that._startX = zot(a.x)?that._startX:a.x;
that._startY = zot(a.y)?that._startY:a.y;
} else {
that._startX = zot(a)?that._startX:a;
that._startY = zot(b)?that._startY:b;
}
that.drawShape();
return that;
};
this.to = function(a, b) {
if (a && !zot(a.x)) {
that._endX = zot(a.x)?that._endX:a.x;
that._endY = zot(a.y)?that._endY:a.y;
} else {
that._endX = zot(a)?that._endX:a;
that._endY = zot(b)?that._endY:b;
}
that.drawShape();
return that;
};
Object.defineProperty(that, 'length', {
get: function() {
return that._length;
},
set: function(value) {
var s = that.length!=0 ? value/that.length : 0;
if (isNaN(s)) return;
var startScaleX = that.scaleX;
var startScaleY = that.scaleY;
that.scaleX *= s;
that.scaleY *= s;
var gStart = that.localToGlobal(that._startX, that._startY);
var gEnd = that.localToGlobal(that._endX, that._endY);
that.scaleX = startScaleX;
that.scaleY = startScaleY;
var lStart = that.globalToLocal(gStart.x, gStart.y);
var lEnd = that.globalToLocal(gEnd.x, gEnd.y);
that.setPoints(lStart, lEnd);
}
});
Object.defineProperty(that, 'startPoint', {
get: function() {
return new zim.Point(that._startX, that._startY);
},
set: function(value) {
that._startX = zot(value.x)?that._startX:value.x;
that._startY = zot(value.y)?that._startY:value.y;
that.drawShape();
}
});
Object.defineProperty(that, 'endPoint', {
get: function() {
return new zim.Point(that._endX, that._endY);
},
set: function(value) {
that._endX = zot(value.x)?that._endX:value.x;
that._endY = zot(value.y)?that._endY:value.y;
that.drawShape();
}
});
Object.defineProperty(that, 'startHead', {
get: function() {
return that._startHead;
},
set: function(value) {
that._startHead = value;
that.drawShape();
}
});
Object.defineProperty(that, 'endHead', {
get: function() {
return that._endHead;
},
set: function(value) {
that._endHead = value;
that.drawShape();
}
});
Object.defineProperty(that, 'startX', {
get: function() {
return that._startX;
},
set: function(value) {
that._startX = value||0;
that.drawShape();
}
});
Object.defineProperty(that, 'startY', {
get: function() {
return that._startY;
},
set: function(value) {
that._startY = value||0;
that.drawShape();
}
});
Object.defineProperty(that, 'endX', {
get: function() {
return that._endX;
},
set: function(value) {
that._endX = value||0;
that.drawShape();
}
});
Object.defineProperty(that, 'endY', {
get: function() {
return that._endY;
},
set: function(value) {
that._endY = value||0;
that.drawShape();
}
});
Object.defineProperty(that, 'points', {
get: function() {
return that._points;
},
set: function(value) {
if (!value) return;
that._points = value;
that.drawShape();
}
});
Object.defineProperty(that, 'lineOrientation', {
get: function() {
return that._lineOrientation;
},
set: function(value) {
if (!value) return;
that._lineOrientation = value;
that.drawShape();
}
});
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NOTE: extends ZIM CustomShape for more properties and a few functions.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function(exact, container) {
var startH = (exact||!zim.isPick(oa[3]))?that._startHead:oa[3];
if (startH) {
if (startH.clone) {
startH = startH.clone();
startH.rotation = that._startHead.startAngle;
}
}
var endH = (exact||!zim.isPick(oa[4]))?that._endHead:oa[4];
if (endH) {
if (endH.clone) {
endH = endH.clone();
endH.rotation = that._endHead.startAngle;
}
}
var newShape = that.cloneProps(new zim.Line((exact||!zim.isPick(oa[0]))?that.length:oa[0], (exact||!zim.isPick(oa[2]))?that.thickness:oa[2], (exact||!zim.isPick(oa[1]))?that.color:oa[1], startH, endH, that.dashed, strokeObj, lineType, that._lineOrientation, curveH, curveV, zim.copy(points), style, this.group, inherit));
if (that.points) newShape.setPoints(that.points);
else newShape.setPoints(that._startX, that._startY, that._endX, that._endY);
if (that.linearGradientParams) newShape.linearGradient.apply(newShape, that.linearGradientParams);
if (that.radialGradientParams) newShape.radialGradient.apply(newShape, that.radialGradientParams);
return newShape;
};
};
zim.extend(zim.Line, zim.CustomShape, "clone", "zimCustomShape", false);
//-53.15
/*--
zim.Squiggle = function(color, thickness, points, length, controlLength, controlType, lockControlType, showControls, lockControls, handleSize, allowToggle, move, dashed, onTop, stickColor, selectColor, selectPoints, editPoints, interactive, strokeObj, style, group, inherit)
Squiggle
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a squiggly line with a number of points.
The points have Bezier controls - little handles that change the shape of the line.
The type of control can be specified overall and individually - and can be hidden or shown
The type of control can be changed by double clicking the point - colors of the handles will change
Points can be added by clicking on the line or removed by SHIFT clicking a point.
CTRL Z will undo adding or removing a point
The shape of the line can be recorded with the recordData() method and recreated with the setData() method
The Squiggle is set by default to show and hide controls when clicked
It is also draggable by default when the controls are showing
It can be set to copy with a shift click
MULTIPLE SELECT
Multiple points can be selected and dragged or moved with the keyboard arrows (moves 10 pixels with shift key down)
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var squiggle = new Squiggle().center(); // makes a line with default 4 points with Bezier controls
var line = new Squiggle({points:2, controlType:"none"}).pos(100,100); // makes a diagonal straight line that is editable
END EXAMPLE
EXAMPLE
// Animate along a Squiggle
// see https://zimjs.com/explore/squiggleAnimate.html for more
var line = new Squiggle().center();
new Circle(10, red).addTo().animate({path:line}, 1000);
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
color - |ZIM VEE| - (default green) the line color as any CSS color including "rgba()" for alpha
thickness - (default 2) the thickness of the line in pixels
points - (default 5) a number of points to start with to make the shape
OR an SVG path like: points:"M0,129.5c22,0,40-31,40-41c0-8-3.2-13-10-13" etc. (also see SVGContainer)
OR an array of points as follows:
[[controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType], [etc]]
controlX and controlY - the x and y location of the control Container which holds the point circle and the two control rectangles
rect1X, rect1Y, rect2X, rect2Y - (default based on controlLength) the x and y location of the control rectangles relative to the control location
circleX and circleY - (default 0) the x and y location of the circle relative to the control location (usually 0, 0)
controlType - (default main controlType parameter or "straight" if not controlType parameter) the point's controlType "none", "mirror", "straight" or "free"
length - (default 300) the default length of line used to create the squiggle (also specifies the squiggle's bounds(0, 0, length, thickness))
controlLength - |ZIM VEE| (default radius*numPoints/4) specify a Number to override the calculated default
controlType - (default "straight") one of four String values as follows:
none - there are no control rectangles (they are actually set at 0,0). This makes a corner at the circle point.
mirror - the control rectangles reflect one another about the point circle - lengths are kept even
straight - the control rectangles keep a straight line through the point circle but length is independent
free - the control rectangle moves independently from the other control rectangle
** The controlType can be specified for each point - see the points parameter
** The controlType can be changed by doubleClicking the point circle to cycle through the controls in the order above - unless the lockControlType is set to true
lockControlType - (default false) set to true to disable doubleClicking of point circles to change controlType
showControls - (default true) set to false to start with controls not showing - can change this after with controlsVisible property or showControls() and hideControls() methods
lockControls - (default false) set to true to lock the editing of controls - can't move the points or handles - but can see them if showControls is set to true
handleSize - (default 20 mobile 10 for non-mobile) the size of control boxes and affects the circles too proportionally
allowToggle - (default true) set false to let turn off clicks showing and hiding controls
move - (default true) set to false to disable dragging when controls are showing
can also set to "always" to allow movement when controls are not showing
dashed - (default false) set to true for dashed border (if borderWidth or borderColor set)
or set to an array of line size then space size, etc.
eg. [20, 10] is 20 line and 10 space repeated and [20,100,50,10] is 20 line, 100 space, 50 line, 10 space, etc.
onTop - (default true) set to false to not bring shape to top of container when dragging
stickColor - (default "#111") set the stick color of the controls
selectColor - (default white) the color of the selected circle or rectangle of the controls if selectPoints is true
selectPoints - (default true) set to false to not allow point controls to be selected for keyboard control
editPoints - (default true) lets user add points by pressing on shape path or remove points by shift click or hold
set to "anywhere" to let users add points anywhere - will add points with controlType:"none"
set to false to not allow adding or removing points with shift click or hold
interactive - (default true) set to false to turn off controls, move, toggle, select, edit - leaving just the shape
strokeObj - (default {caps:"butt", joints:"miter", miterLimit:10, ignoreScale:false}) set to adjust stroke properties
caps options: "butt", "round", "square" or 0,1,2
joints options: "miter", "round", "bevel" or 0,1,2
miterLimit is the ration at which the mitered joint will be clipped
ignoreScale set to true will draw the specified line thickness regardless of object scale
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
approximateBounds(num, showPoints, margin) - update the bounds based on a Rectangle
that surrounds the number of points (default 80) distributed around the object path
set showPoints to true to draw little dots on points
margin increases (or if negative decreases) the bounds on all sides by the margin
use outline() after object has been added to the stage to see the bounds
addPoint(percent, controlType) - add a point at a percent (100) of the total curve
this is handy to make path have the same number of points for animate() path tweens
controlType can be as specified in main points parameter
returns object for chaining
addPoints(num, controlType, startPoint, spread, dataOnly, points) - add num points between existing points
controlType can be as specified in main points parameter
specify a startPoint to add points between the startPoint and the next point (one segment of points)
spread (default false) set to true to spread points evenly around path rather than evenly between segments
dataOnly and points are used internally
returns object for chaining
interpolate(num, startPoint, spread, points, even) - get point data {x,y} for existing points and num (default 1) points inbetween
used with hitTestPath() and animate() drag on path - also add points (note add points does not use even:true)
specify a startPoint to get points between the startPoint and the next point (one segment of points)
spread (default false) set to true to spread number of points around path rather equal number between segments
points (default all points) the points to work with in the same format as the points property
even (default false) set to true to use zim.Bezier() with even turned on for even percentage distribution
returns an array of point objects with x, y properties and an r property for ratio of distance along path
recordData(toJSON) - returns an object with x, y, points, color, borderColor, borderWidth, move, toggle, controls PROPERTIES to be used with setData() method
if toJSON (default false) is set to true, the return value is a JSON string
the points data comes from the points property
setData(data, fromJSON) - sets the properties to match the data object passed in - this should come from recordData()
if fromJSON (default false) is set to true, it will assume a JSON string is passed in as data
the points data is parsed with the set setPoints() so the number of points should be the same
returns object for chaining
recordPoints(popup) - returns an array with the same format as the points parameter - or can just use points property
popup - (default false) set to true to open a zim Pane (squiggle.pane) with the points in a zim TextArea (squiggle.textArea) (click off to close)
NOTE: the TextArea output uses JSON.stringify() - to add the points to the points parameter of the Squiggle use JSON.parse(output);
NOTE: using zog(JSON.stringify(squiggle.recordData()))... the console will remove the quotes from the controlTypes so those would have to be manually put back in before parse() will work
setPoints(data) - sets the Squiggle points to the data from recordPoints
This does not remake the Squiggle but rather shifts the controls so the number of points should be the same
changeControl(index, type, rect1X, rect1Y, rect2X, rect2Y, circleX, circleY, update) - change a control type and properties at an index
accepts ZIM DUO normal parameters or configuration object literal with parameter names as propterties
passing in null as the index will change all points to the specified properties
the update parameter defaults to false so set to true to show update or call update() below
this is so multiple changes can be batched before calling update - for instance when animating blobs.
transformPoints(transformType, amount, x, y) - scale, rotate, move points without affecting controls or borderWidth - returns object for chaining
Note - does not adjust original Bounds
transformType - String any of: "scale", "scaleX", "scaleY", "rotation", "x", "y"
amount - the amount to transform
x, y - (default 0, 0) the x and y position to transform about
update(normalize) - update the Squiggle if animating control points, etc. would do this in a Ticker
set normalize (default false) to true to use pointsAdjusted for rotated and scaled points
and if animating along the path after setting rotation or scale on point
just leave out if only animating points
showControls() - shows the controls (and returns squiggle) also see controlsVisible property
hideControls() - hides the controls (and returns squiggle) also see controlsVisible property
toggle(state - default null) - shows controls if hidden and hides controls if showing (returns the object for chaining)
or pass in true to show controls or false to hide controls
traverse(obj, start, end, time) - animates obj from start point to end point along path - thanks KV for the thought!
set start point greater than end point to traverse backwards
will dispatch a "traversed" event when done
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
getPointAngle(index) - gets the angle made by the tangent at the index provided
getSegmentPoint(point1, point2) - returns an array of [point1, controlPoint1, controlPoint2, point2]
used internally for animating to path and adding removing Bezier points
getAdjacentSegmentData(index) - returns an array of two arrays:
The first is an array of cubic Bezier points for segments adjacent and including the provided point index
each element is in the form of [point1, controlPoint1, controlPoint2, point2]
The second is an array of starting point indexes for the segments that were tested
used internally to drag an animation along the path
getCurvePoint(ratio, segmentRatios, segmentPoints, getAngle) gets a point along whole curve at the ratio (0-1) provided
along with x and y values, the point has a z value that is the index of the squiggle point before the calculated point
if the getAngle parameter is true (default false) the point also has an angle property which is the angle of the tangent at the point
ratio is 0-1 with 0 being at the first point and 1 being at the end of the last segment
segmentRatios and segmentPoints will be calculated if not provided
used internally for animating along the path - if lockControls is true, only animate will precalculate these values
linearGradient([colors],[ratios], x0,y0, x1,y1) - shortcut to thicknessCommand linearGradient method (see properties below)
radialGradient([colors],[ratios], x0,y0,radius0, x1,y1,radius1) - shortcut to thicknessCommand radialGradient method (see properties below)
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact, commands) - makes a copy of the object
exact (default false)
ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
commands (default false) makes clones with current color and borderColor commands of object
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
shape - gives access to the shape of the squiggle
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1, 5) will wiggle the colorRange
stickColor - get or set the stickColor - requires an update() to see changes
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
eg. shape.colorCommand.linearGradient([green, blue ,green], [.2, .5, .8], 0, 0, shape.width, 0)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Fill.html
thickness - get and set the stroke size in pixels
thicknessCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
dashed - get and set the dashed - use true / false or an array (see dashed parameter)
dashedOffset - get and set the offset of the dash (50 default) - can animate this property for a marquee effect
dashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
num - get the number of points - to set, use the points property
points - get or set the points array of the Squiggle in the same format as the points parameter:
[[controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType], [etc]]
pointsAdjusted - get points with any point rotation converted to 0 - see update(true)
pointControls - get an array of controls (a container) - use this to animate controls
pointCircles - get an array of control circles - use this to place some other object at the point
pointObjects - get an array of point objects for each point in the following format:
[[control, circle, rect1, rect2, controlType], [etc.]]
control - the container for the control that holds the circle and rectangles (also see pointControls)
circle - the control point circle (also see pointCircles)
rect1 - the first control point rectangle
rect2 - the second control point rectangle
controlType - the control type: default is "straight" (or null) and there is also "mirror", "free" and "none"
NOTE: control, circle, rect1, rect2 can be positioned or animated and controlType can be changed
NOTE: the update() method must be called if manually changing the control positions or type
NOTE: if constantly animating the controls then use a Ticker.add(function(){squiggle.update();})
NOTE: also see recordData(), setData(), recordPoints(), setPoints() methods for further options
addPointFactor - (default 20) used when placing new points along edge (editPoints is true)
divides the distance between points by this amount - the smaller the more accurate but also slower
addMinDistance - (default 15) edge press needs to be within this distance to add a point to the edge
segmentPoints - a read-only array of cubic Bezier points for each segment
each element is in the form of [point1, controlPoint1, controlPoint2, point2]
used internally to animate to the path and add and remove Bezier points
segmentRatios - a read-only array of cumulative ratio lengths of segments
for instance the default five points (four segments) is [.25, .5, .75, 1]
used internally to animate to the path and attribute proportional time to each segment
controls - access to the container that holds the sets of controls
each control is given a read-only num property
sticks - access to the container that holds the control sticks
lastSelected - access to the last selected (or created) control container
lastSelectedIndex - the index number of the last selected controls
controlsVisible - get or set the visibility of the controls - or use showControls() and hideControls()
toggled - read-only Boolean property as to whether picker is showing
types - get or set the general array for the types ["mirror", "straight", "free", "none"]
changing this or removing a type will adjust the order when the user double clicks the points to change their type
this is not an array of types for each point - see the points property to access the types of each point
lockControls - Boolean to lock controls from being adjusted or not
lockControlType - Boolean to lock the type of the controls in their current state or not
allowToggle - Boolean to get or set clicking to show and hide controls
move - Boolean to drag or not drag Squiggle when controls are showing
can also set to "always" to allow movement when controls are not showing
onTop - get or set the onTop
selectPoints - get or set whether points can be selected
interactive - get or set whether the shape is interactive - toggle, move, change or add controls, etc.
keyFocus - get or set the keyboard focus on the DisplayObject - see also zim.KEYFOCUS
will be set to true if this DisplayObject is the first made or DisplayObject is the last to be used with keyboard
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event for when the bezier controls are adjusted (pressup only)
if monitoring constant change is needed add a pressmove event to Squiggle.controls
the change event object has a transformType property with values of "move", "bezierPoint", "bezierHandle", "bezierSwitch"
dispatches "controlsshow" and "controlshide" events when clicked off and on and toggle is true
dispatches an "update" event if the points are changed or a point is added or removed
this removes all listeners on the old shape and controls
so any custom listeners on shape and controls will need to be re-applied - use the update event to do so
dispatches a "traversed" event when traverse() is done - the event object has an obj property for the traversing object
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
MORE
https://zimjs.com/squiggle
https://www.youtube.com/watch?v=BA1bGBU4itI&list=PLCIzupgRt1pYtMlYPtNTKCtztFBeOtyc0
Note the points property has been split into points and pointObjects (and there have been a few property changes) since the time of the video
--*///+53.2
zim.Squiggle = function(color, thickness, points, length, controlLength, controlType, lockControlType, showControls, lockControls, handleSize, allowToggle, move, dashed, onTop, stickColor, selectColor, selectPoints, editPoints, interactive, strokeObj, style, group, inherit) {
var sig = "color, thickness, points, length, controlLength, controlType, lockControlType, showControls, lockControls, handleSize, allowToggle, move, dashed, onTop, stickColor, selectColor, selectPoints, editPoints, interactive, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Squiggle, arguments, sig, this)) return duo;
z_d("53.2");
this.group = group;
var DS = style===false?{}:zim.getStyle("Squiggle", this.group, inherit);
if (zot(thickness)) thickness = DS.thickness!=null?DS.thickness:6;
if (zot(length)) length = DS.length!=null?DS.length:300;
if (zot(points)) points = DS.points!=null?DS.points:5;
if (typeof points == "string") {
var svgProcessor = new zim.SVGContainer();
points = svgProcessor.processPath(points);
}
var num = typeof points == "number" ? points : points.length;
if (num == 0) return;
if (zot(controlLength)) controlLength = DS.controlLength!=null?DS.controlLength:(length / num);
this.zimCustomShape_constructor(length, controlLength, null, null, false);
this.type = "Squiggle";
this.mouseChildren = true; // set to false in CustomShape
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(color)) color = DS.color!=null?DS.color:zim.blue;
if (color.style) {this.colorCommand = color; color = "black";}
if (zot(controlType)) controlType = DS.controlType!=null?DS.controlType:null;
var originalControlType = controlType;
if (zot(controlType)) controlType = "mirror";
if (zot(lockControlType)) lockControlType = DS.lockControlType!=null?DS.lockControlType:false;
if (zot(interactive)) interactive = DS.interactive!=null?DS.interactive:true;
if (zot(showControls)) showControls = DS.showControls!=null?DS.showControls:interactive;
var _controls = showControls;
if (zot(lockControls)) lockControls = DS.lockControls!=null?DS.lockControls:!interactive;
if (zot(handleSize)) handleSize = DS.handleSize!=null?DS.handleSize:zim.mobile()?20:10;
if (zot(allowToggle)) allowToggle = DS.allowToggle!=null?DS.allowToggle:interactive;
if (zot(move)) move = DS.move!=null?DS.move:interactive;
if (zot(stickColor)) stickColor = DS.stickColor!=null?DS.stickColor:"#111";
if (zot(selectColor)) selectColor = DS.selectColor!=null?DS.selectColor:"#fff";
if (zot(selectPoints)) selectPoints = DS.selectPoints!=null?DS.selectPoints:interactive;
this.stickColor = stickColor;
if (zot(onTop)) onTop = DS.onTop!=null?DS.onTop:true;
if (zot(editPoints)) editPoints = DS.editPoints!=null?DS.editPoints:interactive;
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
var oa = remember(color);
function remember() {return arguments;} // for cloning PICK
color = zim.Pick.choose(color);
var that = this;
var stage;
var types = this.types = ["mirror", "straight", "free", "none"];
this.interactive = interactive;
this.num = num;
this.onTop = onTop;
this.move = move;
this.editPoints = editPoints;
this.allowToggle = allowToggle;
this.lockControlType = lockControlType;
this.selectPoints = selectPoints;
this.lockControls = lockControls;
var _points;
var _pointCircles;
var _pointControls;
that._color = color;
that._thickness = thickness;
that._dashed = dashed;
if (that._dashed && !Array.isArray(that._dashed)) that._dashed = [10, 10];
var shape;
var moveDownEvent;
var movePressEvent;
var moveUpEvent;
var draggingCheck = that.move;
var min = 2; // min distance within which a click will add a point
var mapMove;
var sets;
if (originalControlType && typeof points != "number") {
// override controlType
zim.loop(points, function(point) {
point[8]=originalControlType;
if (originalControlType == "none") {
point[4]=point[5]=point[6]=point[7]=0;
}
});
}
init();
function init() {
if (sets) sets.removeAllEventListeners();
that.num = num = typeof points == "number" ? points : points.length;
num = Math.max(2,num);
controlLength = length / num;
shape = that.shape = new zim.Shape({style:false}).addTo(that);
var sticks = that.sticks = new zim.Shape({style:false}).addTo(that);
if (handleSize <= 0) sticks.removeFrom();
var g = shape.graphics;
g.c();
var s = sticks.graphics;
s.c();
var ballS = handleSize/10*8;
var rectS = handleSize;
if (that.selectPoints) {
that.selectedBalls = new zim.SelectionSet();
that.selectedRect1s = new zim.SelectionSet();
that.selectedRect2s = new zim.SelectionSet();
that.selectionManager = new zim.SelectionManager([
that.selectedBalls,
that.selectedRect1s,
that.selectedRect2s
], "ctrl", false);
} else {
that.selectionManager = new zim.SelectionManager(null, "ctrl");
}
var mobile = zim.mobile();
sets = that.controls = new zim.Container({style:false}).addTo(that); // sets - a set contains a ball and two rects
if (that.interactive) sets.drag({onTop:!mobile});
_points = [];
_pointControls = [];
_pointCircles = [];
var angle, point, temp, set, rect1, rect2, ball, type, setInfo;
for (var i=0; i 0) {
for(var i=0; i 0) {
var diffX = e.target.x-e.target.startX;
var diffY = e.target.y-e.target.startY;
for(var i=0; i0) {
for(var i=0; i endPercent || obj.percentComplete == 0) {
obj.stopAnimate();
e.remove();
var eventObj = new createjs.Event("traversed");
eventObj.obj = obj;
that.dispatchEvent(eventObj);
}
});
return that;
};
that.update = function(normalize) {
if (normalize) {
// located any rotated or scaled points
// and set them back to non-rotated and non-scaled
// but keep control handles at the earlier positions
// need to normalize before doing more manual updates with Beziers
// do not need to normalize if animating blob points
that.points = that.pointsAdjusted;
} else {
that.drawShape();
}
that.zimAnimateChanged = true;
return that;
};
// squiggle
if (that.interactive) {
if (move) shape.drag({onTop:false});
moveDownEvent = shape.on("mousedown", function(e) {
stage = e.target.stage;
startPosition = {x:shape.x, y:shape.y};
if (that.selectPoints) that.keyFocus = true;
upTop();
});
movePressEvent = shape.on("pressmove", function() {
sets.x = shape.x;
sets.y = shape.y;
sticks.x = shape.x;
sticks.y = shape.y;
});
moveUpEvent = shape.on("pressup", function() {
var moveControlCheck = (shape.x != startPosition.x || shape.y != startPosition.y);
var movePoint = shape.localToLocal(that.regX,that.regY,that.parent);
that.x = movePoint.x;
that.y = movePoint.y;
sets.x = sets.y = sticks.x = sticks.y = shape.x = shape.y = 0;
if (moveControlCheck) {
var ev = new createjs.Event("change");
ev.controlType = "move";
that.dispatchEvent(ev);
}
if (stage) stage.update();
});
if (!that.move) stopDragging(true); // true is first time
}
function upTop() {
if (that.onTop) {
var nc = that.parent.numChildren-1;
if (that.parent.getChildAt(nc).type == "Keyboard") nc--;
that.parent.setChildIndex(that, nc);
}
}
that.toggleEvent = that.on("mousedown", function() {
if (!that.allowToggle) return;
if (!_controls) {
that.showControls();
that.dispatchEvent("controlsshow");
}
});
that.added(function() {
stage = that.stage;
if (that.toggleStageEvent) stage.off("stagemousedown", that.toggleStageEvent);
that.toggleStageEvent = stage.on("stagemousedown", function(e) {
if (!that.allowToggle || !that.stage) return;
if (_controls && !that.hitTestPoint(e.stageX/zim.scaX, e.stageY/zim.scaY, false)) {
that.hideControls();
that.dispatchEvent("controlshide");
}
});
});
that.clickEvent = that.on("click", function() {
if (that.ctrlKey) {
setTimeout(function() { // give time for record to work if drag with ctrl down
that.clone(true).addTo(that.stage).mov(0, 100);
if (that.allowToggle) {
that.hideControls();
that.dispatchEvent("controlshide");
}
var ev = new createjs.Event("change");
ev.controlType = "move";
that.dispatchEvent(ev);
that.stage.update();
}, 50);
}
});
that.hideControls = function() {
that.toggled = false;
sets.visible = false;
sticks.visible = false;
_controls = false;
if (that.stage) that.stage.update();
if (!that.allowToggle && that.move) stopDragging();
return that;
};
if (!showControls) that.hideControls();
that.showControls = function() {
that.toggled = true;
// if call this with code then will not trigger a change event - not good for TransformManager.persist()
sets.visible = true;
sticks.visible = true;
_controls = true;
sets.x = shape.x;
sets.y = shape.y;
sticks.x = shape.x;
sticks.y = shape.y;
that.addChildAt(shape,0); // put to bottom incase dragged
if (that.move && !that.allowToggle) startDragging();
if (that.stage) that.stage.update();
return that;
};
that.toggle = function(state) {
if (state===true) that.showControls();
else if (state===false) that.hideControls();
else if (_controls) that.hideControls();
else that.showControls();
return that;
};
that.recordData = function(toJSON) {
if (zot(toJSON)) toJSON = false;
var obj = {
type:"Blob",
index:that.parent?that.parent.getChildIndex(that):-1,
x:that.x, y:that.y,
points:that.recordPoints(),
color:that.color,
thickness:that.thickness,
move:that.move,
toggle:that.allowToggle,
controlsVisible:_controls
};
if (toJSON) return JSON.stringify(obj);
return obj;
};
that.setData = function(data, fromJSON) {
if (zot(data)) return;
if (fromJSON) {
try {
data = JSON.parse(data);
} catch (e) {
return;
}
}
var index = data.index;
if (zot(index)) index = -1;
delete data.index;
var pointData = data.points;
if (!zot(pointData)) that.setPoints(pointData);
delete data.points;
that.num = pointData.length;
for (var d in data) {
that[d] = data[d];
}
if (that.parent) {
that.parent.setChildIndex(that, index);
}
that.update();
return that;
};
that.recordPoints = function(popup) {
// balls are relative to blob but handles are relative to ball
// points is an array of [[ballX, ballY, handleX, handleY, handle2X, handle2Y, type], etc.]
if (zot(popup)) popup = false;
var points = that.points;
if (popup) {
if (!that.pane) {
var pane = that.pane = new zim.Pane({
container:that.stage,
width:Math.min(500, that.stage.width-20),
height:Math.min(500, that.stage.height-20),
draggable:true,
});
var textArea = that.textArea = new zim.TextArea(Math.min(400, that.stage.width-70), Math.min(400, that.stage.height-70));
textArea.centerReg(pane);
}
that.textArea.text = JSON.stringify(points);
that.pane.show();
}
return points;
};
that.setPoints = function(points) {
// adjust blob to match points passed in from recordPoints
var p;
var p2;
for (var i=0; i0?ratios[pointBefore-1]:0;
that.addPoint(100*(lastRatio+(currentRatio-lastRatio)*((closestIndex)/(testNum+1))));
}
}
that.lastSelectedIndex = pointBefore+1;
that.lastSelected = that.controls.getChildAt(that.lastSelectedIndex);
that.stage.update();
}
});
// remove point
that.controls.on("click", function (e) {
that.lastSelected = e.target.parent;
var index = that.lastSelectedIndex = that.controls.getChildIndex(e.target.parent);
if (!that.editPoints) return;
if (that.selectionManager.shiftKey) { // remove
// if (that.selectionManager.currentSet == that.selectedBalls && that.selectedBalls.selections.length > 0) return;
removeControl(e);
}
});
function removeControl(e) {
if (e.target.type == "Circle") {
var index = that.lastSelectedIndex = that.controls.getChildIndex(e.target.parent);
if (that.controls.numChildren <= 2) return;
var points = that.points;
if (that.selectPoints) that.lastPoints = zim.copy(points);
points.splice(index, 1); // remove the point at the index
that.points = points;
that.stage.update();
that.lastSelected = that.lastSelectedIndex = null;
}
}
that.controls.hold(removeControl);
if (!_controls) that.hideControls();
that.dispatchEvent("update");
} // end of init()
// if (that.selectPoints) {
function getCurrentSelected() {
var answer = [];
var currentSet = that.selectionManager.currentSet;
if (currentSet && currentSet.selections && currentSet.selections.length > 0) {
for(var i=0; i= 37 && e.keyCode <= 40) {
var currentSelected = getCurrentSelected();
if (currentSelected.length > 0) {
for(var i=0; i= 37 && e.keyCode <= 40) {
var currentSelected = getCurrentSelected();
if (currentSelected.length > 0) {
for(var i=0; i= that.num-2) {
return [
[that.getSegmentPoint(p[that.num-3], p[that.num-2]),
that.getSegmentPoint(p[that.num-2], p[that.num-1])],
[that.num-3, that.num-2]
];
} else {
return [
[that.getSegmentPoint(p[index-1], p[index]),
that.getSegmentPoint(p[index], p[index+1]),
that.getSegmentPoint(p[index+1], p[index+2])],
[index-1,index,index+1]
];
}
};
that.getCurvePoint = function(ratio, segmentRatios, segmentPoints, getAngle, even) {
if (zot(ratio) || isNaN(ratio)) ratio = 0;
if (zot(segmentRatios)) segmentRatios = that.segmentRatios;
if (zot(segmentPoints)) segmentPoints = that.segmentPoints;
if (zot(getAngle)) getAngle = false;
if (zot(even)) even = false;
var percents = segmentRatios;
var segments = segmentPoints;
var afterIndex = zim.loop(percents, function (p, i) {
if (p >= ratio) return i;
});
var earlierPercent = afterIndex > 0 ? percents[afterIndex-1] : 0;
var localTotal = afterIndex > 0 ? (percents[afterIndex]-percents[afterIndex-1]):percents[afterIndex];
if (!localTotal) return undefined;
var localPercent = (ratio-earlierPercent)/localTotal;
var finalPoint = zim.pointAlongCurve(segments[afterIndex], localPercent, getAngle, true);
var finalFinalPoint = that.localToGlobal(finalPoint.x, finalPoint.y);
finalFinalPoint.angle = finalPoint.angle;
finalFinalPoint.z = afterIndex;
return !zot(finalFinalPoint) ? finalFinalPoint : undefined;
};
function proportion(p1, p2, ratio) {
return {
x:p1.x + (p2.x-p1.x)*ratio,
y:p1.y + (p2.y-p1.y)*ratio
};
}
function insertPointData(points, controls, ratios, percent, controlType, skipPoint, dataOnly, even) {
var index = points.length-1; // adjust for squiggle
var lastRatio = 0;
var currentRatio = 0;
if (percent == 100 && that.type == "Squiggle") percent = 99.99;
percent = (percent+100000)%100;
zim.loop(ratios, function (ratio, i) {
if (percent/100 < ratio) {
index = i;
currentRatio = ratio;
return true;
}
lastRatio = ratio;
});
var segment = that.segmentPoints[index];
var r = currentRatio > 0?(percent/100-lastRatio)/(currentRatio-lastRatio):0;
var point = zim.pointAlongCurve(segment, r, null, even);
var newPoint = [point.x,point.y, 0, 0];
if (skipPoint) return;
if (dataOnly) {
that.interpolatedPoints.push({x:point.x, y:point.y, r:percent/100});
return;
}
if (controlType != "none") {
// calculate new handles and adjust old handles
// [controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType]
var startHandle = proportion(segment[0], segment[1], r);
var midPoint = proportion(segment[1], segment[2], r);
var endHandle = proportion(segment[2], segment[3], r);
var newStartHandle = proportion(startHandle, midPoint, r);
var newEndHandle = proportion(midPoint, endHandle, r);
newPoint[4] = newStartHandle.x-point.x;
newPoint[5] = newStartHandle.y-point.y;
newPoint[6] = newEndHandle.x-point.x;
newPoint[7] = newEndHandle.y-point.y;
var start = that.localToLocal(startHandle.x, startHandle.y, controls[index]);
points[index][6] = start.x;
points[index][7] = start.y;
var end = that.localToLocal(endHandle.x, endHandle.y, controls[(index+1)%points.length]);
points[(index+1)%points.length][4] = end.x;
points[(index+1)%points.length][5] = end.y;
}
if (controlType) newPoint[8] = controlType;
points.splice(index+1, 0, newPoint);
}
this.addPoint = function(percent, controlType) {
if (zot(percent)) percent = 100;
var points = that.points;
var ratios = that.segmentRatios;
var controls = that.pointControls;
controlType = controlType ? controlType : originalControlType;
insertPointData(points, controls, ratios, percent, controlType);
that.points = points;
that.num = points.length;
return that;
};
this.addPoints = function(num, controlType, startPoint, spread, dataOnly, points, even) {
if (zot(points)) points = zim.copy(that.points);
var ratios = zim.copy(that.segmentRatios);
var lastRatio = 0;
if (dataOnly) that.interpolatedPoints = [];
// dataOnly should add points to current point too
// but can't just use current point because sometimes that is static
// like when dragging the shape or a point - it does not register until mouseup
// and things like hitTestPath need that to be dynamic
// So the below does not work:
// if (dataOnly) {
// that.interpolatedPoints = [];
// zim.loop(points, function (point, i) {
// if (!zot(startPoint) && i!=startPoint) return;
// that.interpolatedPoints.push({x:point[0], y:point[1]})
// });
// }
if (spread) var totalPoints = ratios.length*num;
zim.loop(ratios, function (ratio, j) {
if (dataOnly) insertPointData(points, that.pointControls, that.segmentRatios, lastRatio*100, controlType, !zot(startPoint) && j!=startPoint, dataOnly, even);
var numCount = spread?Math.round(totalPoints*(ratio-lastRatio)):num;
var div = 1/(numCount+1);
zim.loop(numCount, function(i) {
var r = lastRatio + (ratio-lastRatio)*div*(i+1);
insertPointData(points, that.pointControls, that.segmentRatios, r*100, controlType, !zot(startPoint) && j!=startPoint, dataOnly, even);
if (!dataOnly && num > 0) that.points = points;
});
lastRatio = ratio;
});
if (dataOnly && that.type == "Squiggle") {
// changed to skipPoint false in zim 10.7.0 - not sure why it was true...
insertPointData(points, that.pointControls, that.segmentRatios, 100, controlType, false, dataOnly, even);
}
if (that.stage) that.stage.update();
that.num = points.length;
return that;
};
this.interpolate = function(num, startPoint, spread, points, even) {
if (zot(num)) num = 1;
// dataOnly will add Point to start point too
that.addPoints(num, "none", startPoint, spread, true, points, even);
return that.interpolatedPoints;
};
this.dispose = function(temp, b, disposing) {
if (!that.shape) return;
zim.gD(that); // globalDispose function for common elements
if (stage && that.toggleStageEvent) stage.off("stagemousedown", that.toggleStageEvent);
that.controls.noDrag(); // sets
that.controls.removeAllEventListeners();
if (that.selectPoints && that.selectionManager) that.selectionManager.dispose();
that.selectedBalls = null;
that.selectedRect1s = null;
that.selectedRect2s = null;
that.selectionManager = null;
that.off("mousedown", that.toggleEvent);
that.off("click", that.clickEvent);
if (temp) {
that.shape.dispose();
that.shape = null;
for (var i=0; i 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact, commands) - makes a copy of the object
exact (default false)
ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
commands (default false) makes clones with current color commands of object
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
shape - gives access to the shape of the blob
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1, 5) will wiggle the colorRange
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
eg. shape.colorCommand.linearGradient([green, blue ,green], [.2, .5, .8], 0, 0, shape.width, 0)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Fill.html
borderColor - get and set the stroke color
borderColorCommand - access to the CreateJS stroke command for bitmap, linearGradient and radialGradient strokes
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Stroke.html
borderWidth - get and set the stroke size in pixels
borderWidthCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
dashed - get and set the dashed - use true / false or an array (see dashed parameter)
dashedOffset - get and set the offset of the dash (50 default) - can animate this property for a marquee effect
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
stickColor - get or set the stick color of the controls - requires an update() to see changes
points - get or set the points array of the Blob in the same format as the points parameter:
a number, a shape string ("circle", "rectangle", "triangle"), a ZIM Circle, Rectangle, Triangle
or an array as follows:
[[controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType], [etc]]
pointsAdjusted - get points with any point rotation converted to 0 - see update(true)
pointControls - get an array of controls (a container) - use this to animate controls
pointCircles - get an array of control circles - use this to place some other object at the point
pointObjects - get an array of point objects for each point in the following format:
[[control, circle, rect1, rect2, controlType], [etc.]]
control - the container for the control that holds the circle and rectangles (also see pointControls)
circle - the control point circle (also see pointCircles)
rect1 - the first control point rectangle
rect2 - the second control point rectangle
controlType - the control type: default is "straight" (or null) and there is also "mirror", "free" and "none"
NOTE: control, circle, rect1, rect2 can be positioned or animated and controlType can be changed
NOTE: the update() method must be called if manually changing the control positions or type
NOTE: if constantly animating the controls then use a Ticker.add(function(){blob.update();})
NOTE: also see recordData(), setData(), recordPoints(), setPoints() methods for further options
addPointFactor - (default 20) used when placing new points along edge (editPoints is true)
divides the distance between points by this amount - the smaller the more accurate but also slower
addMinDistance - (default 15) edge press needs to be within this distance to add a point to the edge
segmentPoints - a read-only array of cubic Bezier points for each segment
each element is in the form of [point1, controlPoint1, controlPoint2, point2]
used internally to animate to the path and add and remove Bezier points
segmentRatios - a read-only array of cumulative ratio lengths of segments
for instance the default four points is [.25, .5, .75, 1]
used internally to animate to the path and attribute proportional time to each segment
controls - access to the container that holds the sets of controls
each control is given a read-only num property
sticks - access to the container that holds the control sticks
lastSelected - access to the last selected (or created) control container
lastSelectedIndex - the index number of the last selected controls
controlsVisible - get or set the visibility of the controls - or use showControls() and hideControls()
types - get or set the general array for the types ["mirror", "straight", "free", "none"]
changing this or removing a type will adjust the order when the user double clicks the points to change their type
this is not an array of types for each point - see the points property to access the types of each point
lockControls - Boolean to lock controls from being adjusted or not
allowToggle - Boolean to get or set clicking to show and hide controls
move - Boolean to drag or not drag Blob when controls are showing
can also set to "always" to allow movement when controls are not showing
lockControlType - Boolean to lock the type of the controls in their current state or not
onTop - get or set the onTop property
selectPoints - get or set whether points can be selected
interactive - get or set whether the shape is interactive - toggle, move, change or add controls, etc.
keyFocus - get or set the keyboard focus on the DisplayObject - see also zim.KEYFOCUS
will be set to true if this DisplayObject is the first made or DisplayObject is the last to be used with keyboard
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event for when the bezier controls are adjusted (pressup only or moving with keys - thanks Yui Kim for find)
if monitoring constant change is needed add a pressmove event to Blob.sets
the change event object has a transformType property with values of "move", "bezierPoint", "bezierHandle", "bezierSwitch"
dispatches "controlsshow" and "controlshide" events when clicked off and on and toggle is true
dispatches an "update" event if the points are changed or a point is added or removed
this removes all listeners on the old shape and controls
so any custom listeners on shape and controls will need to be re-applied - use the update event to do so
dispatches a "traversed" event when traverse() is done - the event object has an obj property for the traversing object
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+53.5
zim.Blob = function(color, borderColor, borderWidth, points, radius, controlLength, controlType, lockControlType, showControls, lockControls, handleSize, allowToggle, move, dashed, onTop, stickColor, selectColor, selectPoints, editPoints, interactive, strokeObj, style, group, inherit) {
var sig = "color, borderColor, borderWidth, points, radius, controlLength, controlType, lockControlType, showControls, lockControls, handleSize, allowToggle, move, dashed, onTop, stickColor, selectColor, selectPoints, editPoints, interactive, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Blob, arguments, sig, this)) return duo;
z_d("53.5");
this.group = group;
var DS = style===false?{}:zim.getStyle("Blob", this.group, inherit);
if (zot(radius)) radius = DS.radius!=null?DS.radius:100;
this.zimCustomShape_constructor(-radius,-radius,radius*2,radius*2,false);
this.type = "Blob";
this.mouseChildren = true; // set to false in CustomShape
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":zim.green);
if (color.style) {this.colorCommand = color; color = "black";}
if (borderColor && borderColor.style) {this.borderColorCommand = borderColor; borderColor = "black";}
if (zot(points)) points = DS.points!=null?DS.points:4;
var num = typeof points == "number" ? points : points.length;
var controlLengthOriginal = controlLength;
if (zot(controlLength)) controlLength = DS.controlLength!=null?DS.controlLength:(radius * 4 / num);
if (zot(controlType)) controlType = DS.controlType!=null?DS.controlType:null;
var originalControlType = controlType;
if (zot(controlType)) controlType = "straight";
if (zot(lockControlType)) lockControlType = DS.lockControlType!=null?DS.lockControlType:false;
if (zot(interactive)) interactive = DS.interactive!=null?DS.interactive:true;
if (zot(showControls)) showControls = DS.showControls!=null?DS.showControls:interactive;
var _controls = showControls;
if (zot(lockControls)) lockControls = DS.lockControls!=null?DS.lockControls:!interactive;
if (zot(handleSize)) handleSize = DS.handleSize!=null?DS.handleSize:(zim.mobile()?20:10);
if (zot(allowToggle)) allowToggle = DS.allowToggle!=null?DS.allowToggle:interactive;
if (zot(move)) move = DS.move!=null?DS.move:interactive;
if (zot(stickColor)) stickColor = DS.stickColor!=null?DS.stickColor:"#111";
if (zot(selectColor)) selectColor = DS.selectColor!=null?DS.selectColor:"#fff";
if (zot(selectPoints)) selectPoints = DS.selectPoints!=null?DS.selectPoints:interactive;
this.stickColor = stickColor;
if (zot(onTop)) onTop = DS.onTop!=null?DS.onTop:true;
if (zot(editPoints)) editPoints = DS.editPoints!=null?DS.editPoints:interactive;
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
var oa = remember(color, borderColor);
function remember() {return arguments;} // for cloning PICK
color = zim.Pick.choose(color);
borderColor = zim.Pick.choose(borderColor);
var that = this;
this.interactive = interactive;
this.num = num;
this.editPoints = editPoints;
this.selectPoints = selectPoints;
this.lockControls = lockControls;
this.onTop = onTop;
this.move = move;
this.allowToggle = allowToggle;
this.lockControlType = lockControlType;
var types = this.types = ["mirror", "straight", "free", "none"];
var _points;
var _pointCircles;
var _pointControls;
that._color = color;
that._borderColor = borderColor;
that._borderWidth = borderWidth;
that._dashed = dashed;
if (that._dashed && !Array.isArray(that._dashed)) that._dashed = [10, 10];
var shape;
var moveDownEvent;
var movePressEvent;
var moveUpEvent;
var stage;
var draggingCheck = that.move;
var min = 2; // distance within which to count as click to add point
var mapMove;
var sets;
points = checkForShape(points);
function checkForShape(shape) {
if (shape=="circle" || shape == "rectangle" || shape =="triangle") {
if (shape == "circle") shape = new zim.Circle(radius);
if (shape == "rectangle") shape = new zim.Rectangle(radius*2,radius*2).centerReg({add:false});
if (shape == "triangle") shape = new zim.Triangle(radius*2,radius*2,radius*2);
}
var points;
if (shape.type == "Circle" || shape.type == "Rectangle" || shape.type == "Triangle") {
var b = shape.getBounds();
if (shape.type == "Circle") {
points = 4;
controlLengthOriginal = controlLength = radius*2*.5523;
} else if (shape.type == "Rectangle") {
shape.centerReg({add:false});
points = [[b.x-b.width/2, b.y-b.height/2],[b.x+b.width/2, b.y-b.height/2],[b.x+b.width/2, b.y+b.height/2],[b.x-b.width/2, b.y+b.height/2]];
that.setBounds(b.x-b.width/2, b.y-b.height/2, b.width, b.height);
that.regX = shape.regX-b.width/2;
that.regY = shape.regY-b.height/2;
// this.rotation = shape.rotation;
// this.scaleX = shape.scaleX;
// this.scaleY = shape.scaleY;
} else if (shape.type == "Triangle") {
points = [[shape.three.x-shape.width/2, shape.three.y+shape.height/2+shape.adjusted],[shape.two.x-shape.width/2, shape.two.y+shape.height/2+shape.adjusted],[shape.one.x-shape.width/2, shape.one.y+shape.height/2+shape.adjusted]];
that.setBounds(b.x-b.width/2, b.y-b.height/2, b.width, b.height);
}
return points;
} else {
return shape;
}
}
if (typeof points == "string") {
var svgProcessor = new zim.SVGContainer();
points = svgProcessor.processPath(points);
}
if (originalControlType && typeof points != "number") {
// override controlType
zim.loop(points, function(point) {
point[8]=originalControlType;
if (originalControlType == "none") {
point[4]=point[5]=point[6]=point[7]=0;
}
});
}
init();
function init() {
if (sets) sets.removeAllEventListeners();
if (that.selectPoints) {
that.selectedBalls = new zim.SelectionSet();
that.selectedRect1s = new zim.SelectionSet();
that.selectedRect2s = new zim.SelectionSet();
that.selectionManager = new zim.SelectionManager([
that.selectedBalls,
that.selectedRect1s,
that.selectedRect2s
], "ctrl", false);
} else {
that.selectionManager = new zim.SelectionManager(null, "ctrl");
}
num = typeof points == "number" ? points : points.length;
if (num <= 0) return;
if (zot(controlLengthOriginal)) controlLength = radius * 4 / num;
shape = that.shape = new zim.Shape({style:false}).addTo(that);
var sticks = that.sticks = new zim.Shape({style:false}).addTo(that);
if (handleSize <= 0) sticks.removeFrom();
var g = shape.graphics;
g.c();
var s = sticks.graphics;
s.c();
var ballS = handleSize/10*8;
var rectS = handleSize;
var mobile = zim.mobile();
sets = that.controls = new zim.Container({style:false}).addTo(that); // sets - a set contains a ball and two rects
if (that.interactive) sets.drag({onTop:!mobile});
_points = [];
_pointControls = [];
_pointCircles = [];
var angle, point, temp, set, rect1, rect2, ball, type, setInfo;
for (var i=0; i 0) { // no border specified or a border > 0
if (!zot(that._borderColor) || !zot(that._borderWidth)) { // either a border color or thickness
if (zot(that._borderColor)) that._borderColor = "black";
if (!that.borderColorCommand) {
that.borderColorCommand = g.s(that._borderColor).command;
if (that._borderColor && that._borderColor.type) that.specialColor(that.borderColorCommand, that._borderColor);
}
if (!that.borderWidthCommand) that.borderWidthCommand = g.ss(that._borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (that._dashed) {
if (!that.borderDashedCommand) that.borderDashedCommand = g.sd(Array.isArray(that._dashed)?that._dashed:[10, 10], that._dashedOffset).command;
}
}
}
var set = _points[0][0];
var ballPoint = set.localToLocal(_points[0][1].x, _points[0][1].y, shape);
g.mt(ballPoint.x, ballPoint.y);
s.c().s(that.stickColor).ss(1);
var currentIndex; var nextIndex;
for (var i=0; i<_points.length; i++) {
var currentIndex = i;
var nextIndex = (i+1)%_points.length;
var set = _points[currentIndex][0];
var ball = _points[currentIndex][1];
var control1 = _points[currentIndex][2];
var control2 = _points[currentIndex][3];
var nextSet = _points[nextIndex][0];
var nextBall = _points[nextIndex][1];
var nextControl1 = _points[nextIndex][2];
var nextControl2 = _points[nextIndex][3];
var control2Point = set.localToLocal(control2.x, control2.y, shape);
var nextControl1Point = nextSet.localToLocal(nextControl1.x, nextControl1.y, shape);
var nextBallPoint = nextSet.localToLocal(nextBall.x, nextBall.y, shape);
g.bt(
control2Point.x, control2Point.y,
nextControl1Point.x, nextControl1Point.y,
nextBallPoint.x, nextBallPoint.y
);
// create the sticks
var ballPoint = set.localToLocal(ball.x, ball.y, shape);
var control1Point = set.localToLocal(control1.x, control1.y, shape);
s.mt(ballPoint.x, ballPoint.y).lt(control1Point.x, control1Point.y);
s.mt(ballPoint.x, ballPoint.y).lt(control2Point.x, control2Point.y);
}
g.cp();
g.append(that.colorCommand);
if (that._dashed) g.append(that.borderDashedCommand);
if (that.borderWidthCommand) g.append(that.borderWidthCommand);
if (that.borderColorCommand) g.append(that.borderColorCommand);
};
that.drawShape();
var startPosition;
sets.on("mousedown", function(e) {
if (that.lockControls) return;
if (that.selectPoints) that.keyFocus = true;
startPosition = {x:e.target.x, y:e.target.y};
if (e.target.rect1) { // then mousedown on ball
var ball = e.target;
ball.startX = ball.x;
ball.startY = ball.y;
ball.rect1.startX = ball.rect1.x;
ball.rect1.startY = ball.rect1.y;
ball.rect2.startX = ball.rect2.x;
ball.rect2.startY = ball.rect2.y;
} else { // mousedown on control
var rect = e.target;
rect.startX = rect.x;
rect.startY = rect.y;
var ball = rect.ball;
var index = ball.index;
var type = controlType;
if (!zot(_points[index][4])) type = _points[index][4];
if (type == "straight") {
var other = rect.other;
var dX = other.x - ball.x;
var dY = other.y - ball.y;
other.stickLength = Math.sqrt(Math.pow(dX,2) + Math.pow(dY,2));
}
}
if (that.selectPoints) {
// need to reset all start points for each control circle and rectangle moved
var currentSet = that.selectionManager.currentSet;
if (currentSet && currentSet.selections && currentSet.selections.length > 0) {
for(var i=0; i 0) {
var diffX = e.target.x-e.target.startX;
var diffY = e.target.y-e.target.startY;
for(var i=0; i0) {
for(var i=0; i endPercent || obj.percentComplete == 0) {
obj.stopAnimate();
e.remove();
var eventObj = new createjs.Event("traversed");
eventObj.obj = obj;
that.dispatchEvent(eventObj);
}
});
return that;
};
that.update = function(normalize) {
if (normalize) {
// located any rotated or scaled points
// and set them back to non-rotated and non-scaled
// but keep control handles at the earlier positions
// need to normalize before doing more manual updates with Beziers
// do not need to normalize if animating blob points
that.points = that.pointsAdjusted;
} else {
that.drawShape();
}
that.zimAnimateChanged = true;
return that;
};
// blob
if (that.move && that.interactive) shape.drag({onTop:false});
moveDownEvent = shape.on("mousedown", function(e) {
stage = e.target.stage;
startPosition = {x:shape.x, y:shape.y};
if (that.selectPoints) that.keyFocus = true;
upTop();
});
movePressEvent = shape.on("pressmove", function() {
sets.x = shape.x;
sets.y = shape.y;
sticks.x = shape.x;
sticks.y = shape.y;
});
moveUpEvent = shape.on("pressup", function() {
var moveControlCheck = (shape.x != startPosition.x || shape.y != startPosition.y);
var movePoint = shape.localToLocal(that.regX,that.regY,that.parent);
that.x = movePoint.x;
that.y = movePoint.y;
sets.x = sets.y = sticks.x = sticks.y = shape.x = shape.y = 0;
if (moveControlCheck) {
var ev = new createjs.Event("change");
ev.controlType = "move";
that.dispatchEvent(ev);
}
stage.update();
});
if (!move) stopDragging(true);
function upTop() {
if (that.onTop) {
var nc = that.parent.numChildren-1;
if (that.parent.getChildAt(nc).type == "Keyboard") nc--;
that.parent.setChildIndex(that, nc);
}
}
that.toggleEvent = that.on("mousedown", function() {
if (!that.allowToggle) return;
if (!_controls) {
that.showControls();
that.dispatchEvent("controlsshow");
}
});
that.added(function() {
stage = that.stage;
if (that.toggleStageEvent) that.stage.off("stagemousedown", that.toggleStageEvent);
that.toggleStageEvent = that.stage.on("stagemousedown", function(e) {
if (!that.allowToggle || !that.stage) return;
if (_controls && !that.hitTestPoint(e.stageX/zim.scaX, e.stageY/zim.scaY, false)) {
that.hideControls();
that.dispatchEvent("controlshide");
}
});
});
that.clickEvent = that.on("click", function() {
if (that.ctrlKey) {
setTimeout(function() { // give time for record to work if drag with ctrl down
that.clone(true).addTo(that.stage).mov(100);
if (that.allowToggle) {
that.hideControls();
that.dispatchEvent("controlshide");
}
var ev = new createjs.Event("change");
ev.controlType = "move";
that.dispatchEvent(ev);
that.stage.update();
}, 50);
}
});
that.hideControls = function() {
that.toggled = false;
sets.visible = false;
sticks.visible = false;
_controls = false;
if (that.stage) that.stage.update();
if (!that.allowToggle && that.move) stopDragging();
return that;
};
if (!_controls) that.hideControls();
that.showControls = function() {
// if call this with code then will not trigger a change event - not good for TransformManager.persist()
that.toggled = true;
sets.visible = true;
sticks.visible = true;
_controls = true;
sets.x = shape.x;
sets.y = shape.y;
sticks.x = shape.x;
sticks.y = shape.y;
that.addChildAt(shape,0); // put to bottom in case dragged
if (that.move && !that.allowToggle) startDragging();
if (that.stage) that.stage.update();
return that;
};
that.toggle = function(state) {
if (state===true) that.showControls();
else if (state===false) that.hideControls();
else if (_controls) that.hideControls();
else that.showControls();
return that;
};
that.recordData = function(toJSON) {
if (zot(toJSON)) toJSON = false;
var obj = {
type:"Blob",
index:that.parent?that.parent.getChildIndex(that):-1,
x:that.x, y:that.y,
points:that.recordPoints(),
color:that.color,
borderColor:that.borderColor,
borderWidth:that.borderWidth,
move:that.move,
toggle:that.allowToggle,
controlsVisible:_controls
};
if (toJSON) return JSON.stringify(obj);
return obj;
};
that.setData = function(data, fromJSON) {
if (zot(data)) return;
if (fromJSON) {
try{
data = JSON.parse(data);
} catch (e) {
return;
}
}
var index = data.index;
if (zot(index)) index = -1;
delete data.index;
var pointData = data.points;
if (!zot(pointData)) that.setPoints(pointData);
delete data.points;
this.num = pointData.length;
for (var d in data) {
that[d] = data[d];
}
if (that.parent) {
that.parent.setChildIndex(that, index);
}
return that;
};
that.recordPoints = function(popup) {
// _pointCircles are relative to blob but handles are relative to ball
// points is an array of [[ballX, ballY, handleX, handleY, handle2X, handle2Y, type], etc.]
if (zot(popup)) popup = false;
var points = that.points;
if (popup) {
if (!pane) {
var pane = that.pane = new zim.Pane({
displayClose:false,
container:that.stage,
width:Math.min(500, that.stage.width-20),
height:Math.min(500, that.stage.height-20),
draggable:true,
});
var textArea = that.textArea = new zim.TextArea(Math.min(400, that.stage.width-70), Math.min(400, that.stage.height-70));
textArea.centerReg(pane);
}
pane.show();
textArea.text = JSON.stringify(points);
}
return points;
};
that.setPoints = function(points) {
// adjust blob to match points passed in from recordPoints
var p;
var p2;
for (var i=0; i0?ratios[pointBefore-1]:0;
that.addPoint(100*(lastRatio+(currentRatio-lastRatio)*(closestIndex/(testNum+1))));
}
}
that.lastSelectedIndex = pointBefore+1;
that.lastSelected = that.controls.getChildAt(that.lastSelectedIndex);
that.stage.update();
}
});
// remove point
that.controlsClickEvent = that.controls.on("click", function (e) {
that.lastSelected = e.target.parent;
var index = that.lastSelectedIndex = that.controls.getChildIndex(e.target.parent);
if (!that.editPoints) return;
if (that.selectionManager.shiftKey) { // remove
removeControl(e);
}
});
function removeControl(e) {
if (e.target.type == "Circle") {
var index = that.lastSelectedIndex = that.controls.getChildIndex(e.target.parent);
if (that.controls.numChildren <= 2) return;
var points = that.points;
if (that.selectPoints) that.lastPoints = zim.copy(points);
points.splice(index, 1); // remove the point at the index
that.points = points;
that.stage.update();
that.lastSelected = that.lastSelectedIndex = null;
}
}
that.controls.hold(removeControl);
if (!_controls) that.hideControls();
that.dispatchEvent("update");
} // end of init()
function getCurrentSelected() {
var answer = [];
var currentSet = that.selectionManager.currentSet;
if (currentSet && currentSet.selections && currentSet.selections.length > 0) {
for(var i=0; i= 37 && e.keyCode <= 40) {
var currentSelected = getCurrentSelected();
if (currentSelected.length > 0) {
for(var i=0; i= 37 && e.keyCode <= 40) {
var currentSelected = getCurrentSelected();
if (currentSelected.length > 0) {
for(var i=0; i= that.num-1) {
return [
[that.getSegmentPoint(p[that.num-2], p[that.num-1]),
that.getSegmentPoint(p[that.num-1], p[0]),
that.getSegmentPoint(p[0], p[1])],
[that.num-2,that.num-1,0]
];
} else {
var lastIndex = (index+2>=that.num)?0:index+2;
return [
[that.getSegmentPoint(p[index-1], p[index]),
that.getSegmentPoint(p[index], p[index+1]),
that.getSegmentPoint(p[index+1], p[lastIndex])],
[index-1,index,index+1]
];
}
};
that.getCurvePoint = function(ratio, segmentRatios, segmentPoints, getAngle) {
if (zot(segmentRatios)) segmentRatios = that.segmentRatios;
if (zot(segmentPoints)) segmentPoints = that.segmentPoints;
if (zot(getAngle)) getAngle = false;
var percents = segmentRatios;
var segments = segmentPoints;
var afterIndex = zim.loop(percents, function (p, i) {
if (p >= ratio) return i;
});
var earlierPercent = afterIndex > 0 ? percents[afterIndex-1] : 0;
var localTotal = afterIndex > 0 ? (percents[afterIndex]-percents[afterIndex-1]):percents[afterIndex];
var localPercent = (ratio-earlierPercent)/localTotal;
var finalPoint = zim.pointAlongCurve(segments[afterIndex], localPercent, getAngle, true);
if (zot(finalPoint)) return undefined;
var finalFinalPoint = that.localToGlobal(finalPoint.x, finalPoint.y);
finalFinalPoint.angle = finalPoint.angle;
finalFinalPoint.z = afterIndex;
return !zot(finalFinalPoint) ? finalFinalPoint : undefined;
};
function proportion(p1, p2, ratio) {
return {
x:p1.x + (p2.x-p1.x)*ratio,
y:p1.y + (p2.y-p1.y)*ratio
};
}
function insertPointData(points, controls, ratios, percent, controlType, skipPoint, dataOnly, even) {
var index = points.length-1; // adjust for squiggle
var lastRatio = 0;
var currentRatio = 0;
if (percent == 100 && that.type == "Squiggle") percent = 99.99;
percent = (percent+100000)%100;
zim.loop(ratios, function (ratio, i) {
if (percent/100 < ratio) {
index = i;
currentRatio = ratio;
return true;
}
lastRatio = ratio;
});
var segment = that.segmentPoints[index];
var r = currentRatio > 0?(percent/100-lastRatio)/(currentRatio-lastRatio):0;
// zog(percent)
// zog(percent/100-currentRatio/ratios.length)
// var r = currentRatio > 0?(percent/100-1/ratios.length*currentRatio)/(currentRatio-lastRatio):0
var point = zim.pointAlongCurve(segment, r, null, even);
var newPoint = [point.x,point.y, 0, 0];
if (skipPoint) return;
if (dataOnly) {
that.interpolatedPoints.push({x:point.x, y:point.y, r:percent/100});
return;
}
if (controlType != "none") {
// calculate new handles and adjust old handles
// [controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType]
var startHandle = proportion(segment[0], segment[1], r);
var midPoint = proportion(segment[1], segment[2], r);
var endHandle = proportion(segment[2], segment[3], r);
var newStartHandle = proportion(startHandle, midPoint, r);
var newEndHandle = proportion(midPoint, endHandle, r);
newPoint[4] = newStartHandle.x-point.x;
newPoint[5] = newStartHandle.y-point.y;
newPoint[6] = newEndHandle.x-point.x;
newPoint[7] = newEndHandle.y-point.y;
var start = that.localToLocal(startHandle.x, startHandle.y, controls[index]);
points[index][6] = start.x;
points[index][7] = start.y;
var end = that.localToLocal(endHandle.x, endHandle.y, controls[(index+1)%points.length]);
points[(index+1)%points.length][4] = end.x;
points[(index+1)%points.length][5] = end.y;
}
if (controlType) newPoint[8] = controlType;
points.splice(index+1, 0, newPoint);
}
this.addPoint = function(percent, controlType) {
if (zot(percent)) percent = 100;
var points = that.points;
var ratios = that.segmentRatios;
var controls = that.pointControls;
controlType = controlType ? controlType : originalControlType;
insertPointData(points, controls, ratios, percent, controlType);
that.points = points;
that.num = points.length;
return that;
};
this.addPoints = function(num, controlType, startPoint, spread, dataOnly, points, even) {
if (zot(points)) points = zim.copy(that.points);
var ratios = zim.copy(that.segmentRatios);
var lastRatio = 0;
if (dataOnly) that.interpolatedPoints = [];
// dataOnly should add points to current point too
// but can't just use current point because sometimes that is static
// like when dragging the shape or a point - it does not register until mouseup
// and things like hitTestPath need that to be dynamic
// So the below does not work:
// if (dataOnly) {
// that.interpolatedPoints = [];
// zim.loop(points, function (point, i) {
// if (!zot(startPoint) && i!=startPoint) return;
// that.interpolatedPoints.push({x:point[0], y:point[1]})
// });
// }
if (spread) var totalPoints = ratios.length*num;
zim.loop(ratios, function (ratio, j) {
if (dataOnly) insertPointData(points, that.pointControls, that.segmentRatios, lastRatio*100, controlType, !zot(startPoint) && j!=startPoint, dataOnly, even);
var numCount = spread?Math.round(totalPoints*(ratio-lastRatio)):num;
var div = 1/(numCount+1);
zim.loop(numCount, function(i) {
var r = lastRatio + (ratio-lastRatio)*div*(i+1);
insertPointData(points, that.pointControls, that.segmentRatios, r*100, controlType, !zot(startPoint) && j!=startPoint, dataOnly, even);
if (!dataOnly && num > 0) that.points = points;
});
lastRatio = ratio;
});
if (dataOnly && that.type == "Squiggle") insertPointData(points, that.pointControls, that.segmentRatios, 100, controlType, null, dataOnly, even);
if (that.stage) that.stage.update();
that.num = points.length;
return that;
};
this.interpolate = function(num, startPoint, spread, points, even) {
if (zot(num)) num = 1;
// dataOnly will add Point to start point too
that.addPoints(num, "none", startPoint, spread, true, points, even);
return that.interpolatedPoints;
};
this.dispose = function(temp, d, disposing) {
if (!that.shape) return;
zim.gD(that); // globalDispose function for common elements
if (stage && that.toggleStageEvent) stage.off("stagemousedown", that.toggleStageEvent);
that.controls.noDrag(); // sets
that.controls.removeAllEventListeners();
if (that.selectPoints && that.selectionManager) that.selectionManager.dispose();
that.selectedBalls = null;
that.selectedRect1s = null;
that.selectedRect2s = null;
that.selectionManager = null;
that.off("mousedown", that.toggleEvent);
that.off("click", that.clickEvent);
if (temp) {
that.shape.dispose();
that.shape = null;
for (var i=0; i0?"rgba(0,0,0,0)":"black");
if (zot(borderWidth) || borderWidth > 0) { // no border specified or a border > 0
if (!zot(borderColor) || !zot(borderWidth)) { // either a border color or thickness
if (zot(borderColor)) borderColor = "black";
}
}
if (zot(crossAngle)) crossAngle = DS.crossAngle!=null?DS.crossAngle:0;
var crossAngleOriginal = crossAngle;
crossAngle -= 90;
if (zot(thickness)) thickness = DS.thickness!=null?DS.thickness:null;
if (zot(thicknessA)) thicknessA = DS.thicknessA!=null?DS.thicknessA:null;
if (zot(thicknessB)) thicknessB = DS.thicknessB!=null?DS.thicknessB:null;
if (zot(thickness)) {
if (zot(thicknessB) && !zot(thicknessA)) thicknessB = thicknessA;
else if (zot(thicknessA) && !zot(thicknessB)) thicknessA = thicknessB;
else thicknessB = thicknessA = 10;
} else {
if (zot(thicknessB) && !zot(thicknessA)) thicknessB = thickness-thicknessA;
else if (zot(thicknessA) && !zot(thicknessB)) thicknessA = thickness-thicknessB;
else thicknessB = thicknessA = thickness/2;
}
that.thickness = thicknessA + thicknessB; // read-only
// from now on - do not use thickness
if (zot(cross)) cross =DS.cross!=null?DS.cross:true;
if (zot(crossColors)) crossColors =DS.crossColors!=null?DS.crossColors:null;
if (!zot(crossColors) && !Array.isArray(crossColors)) crossColors = [crossColors];
if (zot(close)) close = DS.close!=null?DS.close:false;
if (zot(startX)) startX = DS.startX!=null?DS.startX:0;
if (zot(startY)) startY = DS.startY!=null?DS.startY:0;
// lengths, angles, anglesA, anglesB, anglesEnd
if (zot(lengths)) lengths = DS.lengths!=null?DS.lengths:[200];
if (!Array.isArray(lengths)) lengths = [lengths];
if (zot(angles)) angles = DS.angles!=null?DS.angles:[0];
if (!Array.isArray(angles)) angles = [angles];
if (zot(anglesA)) anglesA = DS.anglesA!=null?DS.anglesA:[10];
if (!Array.isArray(anglesA)) anglesA = [anglesA];
if (zot(anglesB)) anglesB = DS.anglesB!=null?DS.anglesB:zim.copy(anglesA);
if (!Array.isArray(anglesB)) anglesB = [anglesB];
if (zot(anglesEnd)) anglesEnd = DS.anglesEnd!=null?DS.anglesEnd:[0];
if (!Array.isArray(anglesEnd)) anglesEnd = [anglesEnd];
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{miterLimit:2};
if (zot(spineBorderColor)) spineBorderColor = DS.spineBorderColor!=null?DS.spineBorderColor:null;
if (zot(spineBorderWidth)) spineBorderWidth = DS.spineBorderWidth!=null?DS.spineBorderWidth:null;
if (spineBorderColor < 0 || spineBorderWidth < 0) spineBorderColor = spineBorderWidth = null;
else if (spineBorderColor!=null && spineBorderWidth==null) spineBorderWidth = 1;
if (zot(spineColor)) spineColor = DS.spineColor!=null?DS.spineColor:(spineBorderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(spineDashed)) spineDashed = DS.spineDashed!=null?DS.spineDashed:null;
if (zot(spineStrokeObj)) spineStrokeObj = DS.spineStrokeObj!=null?DS.spineStrokeObj:{miterLimit:2};
if (zot(spineBorderWidth) || spineBorderWidth > 0) {
if (!zot(spineBorderColor) || !zot(spineBorderWidth)) {
if (zot(spineBorderColor)) spineBorderColor = borderColor?borderColor:"black";
}
}
if (zot(closeBorderColor)) closeBorderColor = DS.closeBorderColor!=null?DS.closeBorderColor:null;
if (zot(closeBorderWidth)) closeBorderWidth = DS.closeBorderWidth!=null?DS.closeBorderWidth:null;
if (closeBorderColor < 0 || closeBorderWidth < 0) closeBorderColor = closeBorderWidth = null;
else if (closeBorderColor!=null && closeBorderWidth==null) closeBorderWidth = 1;
if (zot(closeColor)) closeColor = DS.closeColor!=null?DS.closeColor:(closeBorderWidth>0?"rgba(0,0,0,0)":null);
if (zot(closeDashed)) closeDashed = DS.closeDashed!=null?DS.closeDashed:null;
if (zot(closeStrokeObj)) closeStrokeObj = DS.closeStrokeObj!=null?DS.closeStrokeObj:{miterLimit:2};
if (zot(closeBorderWidth) || closeBorderWidth > 0) {
if (!zot(closeBorderColor) || !zot(closeBorderWidth)) {
if (zot(closeBorderColor)) closeBorderColor = borderColor?borderColor:"black";
}
}
this.thicknessA = thicknessA;
this.thicknessB = thicknessB;
this.cross = cross;
this.close = close;
this.lengths = lengths;
this.angles = angles;
this.anglesA = anglesA;
this.anglesB = anglesB;
this.anglesEnd = anglesEnd;
this.crossColors = crossColors;
drawShape(lengths, angles, anglesA, anglesB, anglesEnd, cross, crossColors, close);
function drawShape(lengths, angles, anglesA, anglesB, anglesEnd, cross, crossColors, close) {
that.removeAllChildren();
var s = that.shape = new zim.Shape().addTo(that);
that.colorCommand = s.c().f(color).command;
if (color && color.type) that.specialColor(that.colorCommand, color);
if (zot(borderWidth) || borderWidth > 0) {
if (!zot(borderColor) || !zot(borderWidth)) {
if (zot(borderColor)) borderColor = "black";
that.borderColorCommand = s.s(borderColor).command;
if (borderColor && borderColor.type) that.specialColor(that.borderColorCommand, borderColor);
that.borderWidthCommand = s.ss(borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (dashed) that.borderDashedCommand = s.sd([10, 10], 5).command;
}
}
s.mt(0,0);
if (spineBorderWidth > 0) {
var spineS = that.spineShape = new zim.Shape().addTo(that);
that.spineColorCommand = spineS.c().f(spineColor).command;
if (spineColor && spineColor.type) that.specialColor(that.spineColorCommand, spineColor);
if (zot(spineBorderWidth) || spineBorderWidth > 0) {
if (!zot(spineBorderColor) || !zot(spineBorderWidth)) {
if (zot(spineBorderColor)) spineBorderColor = "black";
that.spineBorderColorCommand = spineS.s(spineBorderColor).command;
if (spineBorderColor && spineBorderColor.type) that.specialColor(that.spineBorderColorCommand, spineBorderColor);
that.spineBorderWidthCommand = spineS.ss(spineBorderWidth, spineStrokeObj.caps, spineStrokeObj.joints, spineStrokeObj.miterLimit, spineStrokeObj.ignoreScale).command;
if (spineDashed) that.spineBorderDashedCommand = spineS.sd([10, 10], 5).command;
}
}
}
if (!zot(closeColor)) {
var closeS = that.closeShape = new zim.Shape().addTo(that);
that.closeColorCommand = closeS.c().f(closeColor).command;
if (closeColor && closeColor.type) that.specialColor(that.closeColorCommand, closeColor);
if (zot(closeBorderWidth) || closeBorderWidth > 0) {
if (!zot(closeBorderColor) || !zot(closeBorderWidth)) {
if (zot(closeBorderColor)) closeBorderColor = "black";
that.closeBorderColorCommand = closeS.s(closeBorderColor).command;
if (closeBorder && closeBorder.type) that.specialColor(that.closeBorderCommand, closeBorderColor);
that.closeBorderWidthCommand = closeS.ss(closeBorderWidth, closeStrokeObj.caps, closeStrokeObj.joints, closeStrokeObj.miterLimit, closeStrokeObj.ignoreScale).command;
if (closeDashed) that.closeBorderDashedCommand = closeS.sd([10, 10], 5).command;
}
}
s.mt(0,0);
}
// start values
var sX = startX;
var sY = startY;
var f2 = crossAngle;
var f = f2-180;
var tA = thicknessA;
var tB = thicknessB;
var lastAngle = angles[0];
var num = Math.max(lengths.length, angles.length, anglesA.length, anglesB.length, anglesEnd.length);
var lastB, lastC;
var lastAngle = f;
var pointsA = [];
var pointsB = [];
var pointsC = [];
var points = that.points = [];
var spines = that.pinPoints = [];
zim.loop(num, function(i, t) {
var data = getSegment(i);
var cosine = Math.cos(data.a*zim.RAD);
var sine = Math.sin(data.a*zim.RAD);
var AA = new zim.Point(sX+data.A.x*cosine-data.A.y*sine, sY+data.A.x*sine+data.A.y*cosine);
var BB = new zim.Point(sX+data.B.x*cosine-data.B.y*sine, sY+data.B.x*sine+data.B.y*cosine);
var CC = new zim.Point(sX+data.C.x*cosine-data.C.y*sine, sY+data.C.x*sine+data.C.y*cosine);
var DD = new zim.Point(sX+data.D.x*cosine-data.D.y*sine, sY+data.D.x*sine+data.D.y*cosine);
pointsA.push(AA,BB);
pointsB.unshift(CC,DD);
pointsC.push([AA,BB,CC,DD]); // for cross
var FF = new zim.Point(sX+data.F.x*cosine-data.F.y*sine, sY+data.F.x*sine+data.F.y*cosine);
var EE = new zim.Point(sX+data.E.x*cosine-data.E.y*sine, sY+data.E.x*sine+data.E.y*cosine);
if (i==0) that.pinPoints.push(FF);
that.pinPoints.push(EE);
sX = EE.x;
sY = EE.y;
tA = data.tA;
tB = data.tB;
});
that.points = pointsA.concat(pointsB);
if (!cross) {
zim.loop(pointsA, function (point, i) {
if (i==0) s.mt(point.x, point.y);
else s.lt(point.x, point.y);
});
if (close) {
s.lt(pointsA[0].x, pointsA[0].y);
s.cp();
}
zim.loop(pointsB, function (point, i) {
if (i==0 && close) s.mt(point.x, point.y);
else s.lt(point.x, point.y);
});
if (close) {
s.lt(pointsB[0].x, pointsB[0].y);
}
s.cp();
} else {
zim.loop(pointsC, function (points, i) {
s .mt(points[0].x, points[0].y);
if (!zot(crossColors) && !zot(crossColors[i])) s.f(crossColors[i]).mt(points[0].x, points[0].y);
s .lt(points[1].x, points[1].y)
.lt(points[2].x, points[2].y)
.lt(points[3].x, points[3].y)
.cp();
});
if (close) {
s .mt(pointsC[pointsC.length-1][1].x, pointsC[pointsC.length-1][1].y)
.lt(pointsC[pointsC.length-1][2].x, pointsC[pointsC.length-1][2].y)
.lt(pointsC[0][3].x, pointsC[0][3].y)
.lt(pointsC[0][0].x, pointsC[0][0].y)
.cp();
}
}
if (spineS) {
zim.loop(spines, function (spine,i) {
if (i==0) spineS.mt(spine.x, spine.y);
else spineS.lt(spine.x, spine.y);
});
if (close) {
spineS.lt(spines[0].x, spines[0].y).cp();
}
}
if (!zot(closeColor)) {
zim.loop(pointsB, function (point,i) {
if (i==0) closeS.mt(point.x, point.y);
else closeS.lt(point.x, point.y);
});
if (close) {
closeS.lt(pointsB[0].x, pointsB[0].y).cp();
}
}
// segment values
function getSegment(num) {
var a = angles[num];
var d = lengths[num];
var aA = anglesA[num];
var aB = anglesB[num];
var e = anglesEnd[num];
if (crossColors) var cc = crossColors[num];
if (zot(a)) {a = lastAngle; that.angles[num] = a;}
if (zot(d)) {d = 200; that.lengths[num] = d;}
if (zot(aA)) {aA = 0; that.anglesA[num] = aA;}
if (zot(aB)) {aB = 0; that.anglesB[num] = aB;}
if (zot(e)) {e = 0; that.anglesEnd[num] = e;}
if (crossColors && zot(cc)) {cc = color; that.crossColors[num] = cc;}
e = e+90;
var e2 = 180-e;
var cosine = Math.cos((lastAngle-a)*zim.RAD);
var sine = Math.sin((lastAngle-a)*zim.RAD);
// GOAL is to find points F, A, B, C, D, E
var F = new zim.Point(0,0);
var E = new zim.Point(d,0);
if (zot(lastB)) {
var A = new zim.Point(Math.cos(f2*zim.RAD)*tA, Math.sin(f2*zim.RAD)*tA);
} else {
A = new zim.Point(lastB.x*cosine-lastB.y*sine, lastB.x*sine+lastB.y*cosine);
}
var pA = getEnd(d, A.x, A.y, aA, e2);
var B = new zim.Point(d-pA.x, -pA.y);
if (zot(lastC)) {
var D = new zim.Point(Math.cos(f*zim.RAD)*tA, Math.sin(f*zim.RAD)*tB);
} else {
var D = new zim.Point(lastC.x*cosine-lastC.y*sine, lastC.x*sine+lastC.y*cosine);
}
var pB = getEnd(d, D.x, D.y, aB, e);
var C = new zim.Point(d-pB.x, pB.y);
lastB = new zim.Point(B.x-d, B.y);
lastC = new zim.Point(C.x-d, C.y);
lastAngle = a;
// all the points, next start thickness AB
return {a:a, A:A, B:B, C:C, D:D, E:E, F:F, tA:pA.t, tB:pB.t};
}
function getEnd(dist, frontX, frontY, flare, endAngle) {
var u = endAngle-90;
var w = 90-u;
var v = 180-flare-w;
var n = Math.tan(u*zim.RAD)*frontY;
var s = dist-frontX-n;
var t1 = s/Math.sin(v*zim.RAD)*Math.sin(flare*zim.RAD);
var t2 = Math.sqrt(Math.pow(frontY,2) + Math.pow(n,2));
var t = t1 + t2;
var x = t*Math.sin(u*zim.RAD);
var y = t*Math.cos(u*zim.RAD);
return {x:x,y:y,t:t};
}
} // end makeShape
// METHODS
this.add = function(lengths, angles, anglesA, anglesB, anglesEnd, cross, crossColors, close) {
var sig = "lengths, angles, anglesA, anglesB, anglesEnd, cross, crossColors, close";
var duo; if (duo = zob(that.add, arguments, sig)) return duo;
if (!zot(cross)) that.cross = cross;
if (!zot(close)) that.close = close;
if (!zot(lengths)) {
if (!Array.isArray(lengths)) lengths = [lengths];
if (zot(that.lengths)) that.lengths = lengths;
else that.lengths = that.lengths.concat(lengths);
}
if (!zot(angles)) {
if (!Array.isArray(angles)) angles = [angles];
if (zot(that.angles)) that.angles = angles;
else that.angles = that.angles.concat(angles);
}
if (!zot(anglesA)) {
if (!Array.isArray(anglesA)) anglesA = [anglesA];
if (zot(that.anglesA)) that.anglesA = anglesA;
else that.anglesA = that.anglesA.concat(anglesA);
}
if (!zot(anglesB)) {
if (!Array.isArray(anglesB)) anglesB = [anglesB];
if (zot(that.anglesB)) that.anglesB = anglesB;
else that.anglesB = that.anglesB.concat(anglesB);
}
if (!zot(anglesEnd)) {
if (!Array.isArray(anglesEnd)) anglesEnd = [anglesEnd];
if (zot(that.anglesEnd)) that.anglesEnd = anglesEnd;
else that.anglesEnd = that.anglesEnd.concat(anglesEnd);
}
if (!zot(crossColors)) {
if (zot(that.crossColors)) {
if (zon) zogy("Flare() - must set crossColor for original object parameters");
} else {
if (!Array.isArray(crossColors)) crossColors = [crossColors];
if (zot(that.crossColors)) that.crossColors = crossColors;
else that.crossColors = that.crossColors.concat(crossColors);
}
}
that.remake();
return that;
};
this.remake = function() {
thicknessA = this.thicknessA;
thicknessB = this.thicknessB;
drawShape(that.lengths, that.angles, that.anglesA, that.anglesB, that.anglesEnd, that.cross, that.crossColors, that.close);
return that;
};
// PROPERTIES
Object.defineProperty(that, 'color', {
get: function() {
return color;
},
set: function(value) {
if (zot(value)) value = "black";
color = value;
if (value && value.type) that.specialColor(that.colorCommand, value);
else that.colorCommand.style = value;
}
});
var startColor;
var endColor;
this.setColorRange = function(color1, color2) {
if (zot(color2)) {
startColor = that.color;
endColor = color1;
} else if (zot(color1)) {
startColor = that.color;
endColor = color2;
} else {
startColor = color1;
endColor = color2;
}
return that;
};
var colorRange = 0;
Object.defineProperty(that, 'colorRange', {
get: function() {
return colorRange;
},
set: function(value) {
colorRange = value;
if (!zot(startColor) && !zot(endColor)) {
that.color = zim.colorRange(startColor, endColor, value);
}
}
});
Object.defineProperty(that, 'borderColor', {
get: function() {
return borderColor;
},
set: function(value) {
borderColor = value;
if (!that.borderColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.borderColorCommand, value);
else that.borderColorCommand.style = value;
}
});
Object.defineProperty(that, 'borderWidth', {
get: function() {
return borderWidth;
},
set: function(value) {
if (!(value>0)) value = 0;
borderWidth = value;
if (!that.borderWidthCommand || borderWidth == 0) drawShape();
else {
that.borderWidthCommand.width = borderWidth;
if (dashed) {
that.borderDashedCommand.segments = [20, 10];
that.borderDashedCommand.offset = 5;
}
}
}
});
Object.defineProperty(that, 'spineColor', {
get: function() {
return spineColor;
},
set: function(value) {
if (zot(value)) value = "black";
spineColor = value;
if (!that.spineColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.spineColorCommand, value);
else that.spineColorCommand.style = value;
}
});
Object.defineProperty(that, 'spineBorderColor', {
get: function() {
return spineBorderColor;
},
set: function(value) {
spineBorderColor = value;
if (!that.spineBorderColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.spineBorderColorCommand, value);
else that.spineBorderColorCommand.style = value;
}
});
Object.defineProperty(that, 'spineBorderWidth', {
get: function() {
return spineBorderWidth;
},
set: function(value) {
if (!(value>0)) value = 0;
spineBorderWidth = value;
if (!that.spineBorderWidthCommand || spineBorderWidth == 0) drawShape();
else {
that.spineBorderWidthCommand.width = spineBorderWidth;
if (spineDashed) {
that.spineBorderDashedCommand.segments = [20, 10];
that.spineBorderDashedCommand.offset = 5;
}
}
}
});
Object.defineProperty(that, 'closeColor', {
get: function() {
return closeColor;
},
set: function(value) {
if (zot(value)) value = "black";
closeColor = value;
if (!that.closeColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.closeColorCommand, value);
else that.closeColorCommand.style = value;
}
});
Object.defineProperty(that, 'closeBorderColor', {
get: function() {
return closeBorderColor;
},
set: function(value) {
closeBorderColor = value;
if (!that.closeBorderColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.closeBorderColorCommand, value);
else that.closeBorderColorCommand.style = value;
}
});
Object.defineProperty(that, 'closeBorderWidth', {
get: function() {
return closeBorderWidth;
},
set: function(value) {
if (!(value>0)) value = 0;
closeBorderWidth = value;
if (!that.closeBorderWidthCommand || closeBorderWidth == 0) drawShape();
else {
that.closeBorderWidthCommand.width = closeBorderWidth;
if (closeDashed) {
that.closeBorderDashedCommand.segments = [20, 10];
that.closeBorderDashedCommand.offset = 5;
}
}
}
});
Object.defineProperty(that, 'pin', {
get: function() {
return pin;
},
set: function(value) {
if (!(value>0)) value = 0;
if (value > that.pinPoints.length-1) pin = 0;
pin = value;
var point = that.pinPoints[pin];
if (point) {
that.regX = point.x;
that.regY = point.y;
}
}
});
var b = zim.boundsAroundPoints(that.points);
this.setBounds(b.x, b.y, b.width, b.height);
if (!zot(pin)) that.pin = pin;
this.mouseChildren = false;
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Flare(color, borderColor, borderWidth, crossAngleOriginal, zim.copy(thickness), zim.copy(thicknessA), zim.copy(thicknessB), pin, startX, startY, zim.copy(lengths), zim.copy(angles), zim.copy(anglesA), zim.copy(anglesB), zim.copy(anglesEnd), cross, zim.copy(crossColors), close, dashed, strokeObj, spineColor, spineBorderWidth, spineBorderColor, spineDashed, spineStrokeObj, closeColor, closeBorderWidth, closeBorderColor, closeDashed, closeStrokeObj, style, this.group, inherit));
};
};
zim.extend(zim.Flare, zim.Container, ["clone"], "zimContainer", false);
//-53.6
//
/*--
zim.MultiFlare = function(flares, pins, angles, endToEnd, style, group, inherit)
MultiFlare
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Joins multiple Flare objects in one container
at the pin points of the flares or end to end.
See also ZIM Flare and ZIM FlareBox.
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// a fan of legs with feet!
var flare = new Flare({lengths:[100,100,20,8],anglesA:[5,-5,60],anglesB:[5,-5,0]})
var multi = new MultiFlare().center();
loop(12, function (i) {
multi.add(flare.rot(i*360/12))
});
// or prepare flares and angles ahead of time
var flares = [];
var angles = [];
loop(12, function (i) {
flares.push(flare.clone());
angles.push(i*360/12);
});
new MultiFlare(flares, null, angles).center();
// a ring of beads using endToEnd
var flare = new Flare({crossAngle:-360/12, lengths:[50,20,5,20,50],anglesA:[5,60,0,-60,-5]})
var flares = [];
var angles = [];
loop(12, function (i) {
flares.push(flare.clone());
angles.push(i*360/12);
});
new MultiFlare(flares, null, angles, true).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
flares - (default null) an array of ZIM Flares objects to add - also see add() method
pins - (default null) an array of pin indexes for the flares
pins will set the registration point for each flare at whatever segment matches the pin index
angles - (default null) an array angles for the flares
endToEnd - (default false) set to true to locate each first segment point of the flare at the last segment point of the last flare
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
add(flares) - add an array of flares or a single flare to MultiFlare
add() redraws the whole flare so for many, make an array to start and pass it in as an argument
remove(flares) - remove an array of flares or a single flare to MultiFlare
remove() redraws the whole flare so for many, make an array to start and pass it in as an argument
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy of the multiFlare cloning the flares too
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
** can get and change the following properties
** see the paremeters for details
** if properties are changed call the remake() method to update the MultiFlare
flares - array
pins - array
angles - array
endToEnd - boolean
mouseChildren - set to false to avoid dragging the shape inside
to drag or interact with objects inside then set mouseChildren to true
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+53.7
zim.MultiFlare = function(flares, pins, angles, endToEnd, style, group, inherit) {
var sig = "flares, pins, angles, endToEnd, style, group, inherit";
var duo; if (duo = zob(zim.MultiFlare, arguments, sig, this)) return duo;
z_d("53.7");
this.zimContainer_constructor();
this.type = "MultiFlare";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
var that = this;
if (zot(flares)) flares = DS.flares!=null?DS.flares:[];
if (!Array.isArray(flares)) flares = [flares];
// pins, angles, endToEnd
if (zot(pins)) pins = DS.pins!=null?DS.pins:null;
if (zot(angles)) angles = DS.angles!=null?DS.angles:null;
if (zot(endToEnd)) endToEnd = DS.endToEnd!=null?DS.endToEnd:false;
that.flares = flares;
that.pins = pins;
that.angles = angles;
that.endToEnd = endToEnd;
that.mouseChildren = false;
that.add = function(f, clone) {
if (zot(f)) return that;
if (zot(clone)) clone = true;
if (!Array.isArray(f)) f = [f];
zim.loop(f, function (flare) {
if (clone) that.flares.push(flare.clone());
else that.flares.push(flare);
});
that.remake();
if (that.stage) that.stage.update();
return that;
};
that.remove = function(f) {
if (zot(f)) return that;
if (!Array.isArray(f)) f = [f];
zim.loop(f, function (flare) {
var index = that.flares.indexOf(flare);
if (index>=0) that.flares.splice(index, 1);
});
that.remake();
if (that.stage) that.stage.update();
return that;
};
that.remake = function () {
that.removeAllChildren();
zim.loop(that.flares, function (flare, i) {
if (pins && !zot(pins[i])) flare.pin = pins[i];
if (angles && !zot(angles[i])) flare.rotation = angles[i];
flare.addTo(that);
that.flares.push(flare);
if (endToEnd) {
if (i>0) {
var last = flares[i-1];
var lastPoint = last.pinPoints[last.pinPoints.length-1];
var point1 = last.localToLocal(lastPoint.x, lastPoint.y, that);
var firstPoint = flare.pinPoints[0];
var point2 = flare.localToLocal(firstPoint.x, firstPoint.y, that);
flare.mov(point1.x-point2.x, point1.y-point2.y);
}
}
});
};
that.remake();
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.MultiFlare(zim.copy(flares,true), zim.copy(pins), zim.copy(angles), endToEnd, style, this.group, inherit));
};
};
zim.extend(zim.MultiFlare, zim.Container, ["clone"], "zimContainer", false);
//-53.7
/*--
zim.FlareBox = function(width, height, color, borderColor, borderWidth, flares, corners, pins, style, group, inherit)
FlareBox
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a Rectangle with ZIM Flare objects positioned around edges and corners.
Pass in an array of Flare objects or a MultiFlare
FlareBox places flares at specified corner indexes depending on flare pin index.
See also ZIM Flare and ZIM MultiFlare.
A FlareBox can be used as a backing and rollBacking for buttons and other components
to create exciting borders inspired by the tail lights of 2020 automibiles.
See: https://zimjs.com/ten/flare.html
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var border1 = new Flare({
thickness:6,
angles:[0,90], // to the right then down
lengths:[60,90],
anglesA:[3,-1.5], // flare angles
anglesEnd:[45,0], // 0 is optional
color:white,
pin:1 // pin at flare corner
});
var border2 = new Flare({
thickness:25,
angles:[0,90], // to right then down
lengths:[50,50],
anglesA:[-2,2], // anglesB will mirror these if not provided
anglesEnd:[45],
color:dark,
pin:1 // pin at flare corner
});
// put both flares at left top corner 0
// they each have pin of 1 so
// the rotation is (0-1)*90 = -90 (counter clockwise)
// they were to the right and down
// now they are up and to the right
var flareBox = new FlareBox(220, 100, blue, dark, 3, [border1, border2], [0,0])
.centerReg();
// clone the flares for the rollover FlareBox
// put the first flare at corner 2
// the rotation becomes (2-1)*90 = 90 (clockwise)
// it was built to go to the right and down
// now it is going down and to the left
var flareBoxOver = new FlareBox(220, 100, green, dark, 3, [border1.clone(), border2.clone()], [2,0])
.centerReg({add:false});
// use the flareBoxes as backings
var button = new Button({
width:flareBox.width,
height:flareBox.height,
backing:flareBox,
rollBacking:flareBoxOver
}).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 220) the width of the rectangle about which the Flare objects are placed
this is a little larger than the ZIM Button default width
height - (default 80) the height of the rectangle about which the Flare objects are placed
this is a little larger than the ZIM Button default height
color - (default "black") the fill color as any CSS color including "rgba()" for alpha fill (set a to 0 for tranparent fill)
borderColor - (default null) the stroke color
borderWidth - (default 1 if stroke is set) the size of the stroke in pixels
flares - (default null) an array of ZIM Flare objects or a single flare or a ZIM MultiFlare
corners - (default [0]) an array of corner indexes to place the pin points of the ZIM Flare objects
corner indexes are:
0 - LEFT TOP
1 - RIGHT TOP
2 - RIGHT BOTTOM
3 - LEFT BOTTOM
pins - (default null) an array of pins of the ZIM Flare objects
The pin index can be set on the Flare or through the MultiFlare or here in the FlareBox
The pin is also the registration point of the flare so the flare will be placed at the corner at its pin
FlareBox will also automatically rotate the flares with this formula:
flare.rotation = (corner-pin)*90
This formula allows for easy setting of angles on corners
See the Button at https://zimjs.com/ten/flare.html
This can be overridden by setting the flare rotation after the FlareBox is created
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy of the flareBox and clone flares as well
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
multiFlare - gives access to the ZIM Multiflare object
this is made automatically by FlareBox if an array of flares was used
flares - an array of flares that belong to the multiFlare
backing - gives access to the rectangle backing shape
color - get and set the fill color of the backing shape
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the backing shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1, 5) will wiggle the colorRange
borderColor - get and set the stroke color
borderWidth - get and set the stroke size in pixels
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
mouseChildren - set to false to avoid dragging the shape inside
to drag or interact with objects inside then set mouseChildren to true
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+53.8
zim.FlareBox = function(width, height, color, borderColor, borderWidth, flares, corners, pins, style, group, inherit) {
var sig = "width, height, color, borderColor, borderWidth, flares, corners, pins, style, group, inherit";
var duo; if (duo = zob(zim.FlareBox, arguments, sig, this)) return duo;
z_d("53.8");
this.group = group;
var DS = style===false?{}:zim.getStyle("FlareBox", this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:220;
if (zot(height)) height = DS.height!=null?DS.height:80;
this.zimContainer_constructor(width, height);
this.type = "FlareBox";
var that = this;
this.mouseChildren = false;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(borderWidth) || borderWidth > 0) { // no border specified or a border > 0
if (!zot(borderColor) || !zot(borderWidth)) { // either a border color or thickness
if (zot(borderColor)) borderColor = "black";
}
}
if (zot(flares)) flares = DS.flares!=null?DS.flares:null;
if (zot(corners)) corners = DS.corners!=null?DS.corners:null;
if (zot(pins)) pins = DS.pins!=null?DS.pins:null;
that.backing = new zim.Rectangle(width, height, color, borderColor, borderWidth).addTo(this);
if (zot(flares)) return;
if (flares.type != "MultiFlare") {
if (!Array.isArray(flares)) {
if (flares.type != "Flare") return;
flares = [flares];
}
flares = new zim.MultiFlare(flares, pins);
}
flares.addTo(that);
that.multiFlare = flares;
that.flares = that.multiFlare.flares;
flares.loop(function(flare, i) {
if (pins && !zot(pins[i])) flare.pin = pins[i];
else if (zot(flare.pin)) flare.pin = 0;
if (corners && !zot(corners[i])) flare.corner = corners[i];
else if (zot(flare.corner)) flare.corner = 0;
if (flare.corner==1) {
flare.loc(width,0);
} else if (flare.corner==2) {
flare.loc(width,height);
} else if (flare.corner==3) {
flare.loc(0,height);
} else {
flare.loc(0,0);
}
flare.rot((flare.corner-flare.pin)*90);
});
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.FlareBox(width, height, color, borderColor, borderWidth, zim.copy(flares,true), zim.copy(corners), zim.copy(pins), style, this.group, inherit));
};
};
zim.extend(zim.FlareBox, zim.Container, ["clone"], "zimContainer", false);
//-53.8
// SUBSECTION COMPONENTS
/*--
zim.Label = function(text, size, font, color, rollColor, shadowColor, shadowBlur, align, valign, bold, italic, variant, lineWidth, lineHeight, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, splitWords, style, group, inherit)
Label
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a label - wraps the createjs Text object.
Can use with Button, CheckBox, RadioButtons and Pane.
Text seems to come in different sizes so we do our best.
Have tended to find that left and alphabetic are most consistent across browsers.
Custom fonts loaded through css can be used as well.
NOTE: can wrap text at given width using lineWidth (or labelWidth) parameter.
To dynamically change the width without changing the font size use the labelWidth property.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
new Label("Hello").center(); // adds label to and centers on the stage
new Label({
text:"CLICK",
size:100,
font:"courier",
color:"white",
rollColor:"red",
bold:true,
italic:true
}).loc(100,100).tap(function(){zog("tapping");});
END EXAMPLE
EXAMPLE
// with text that wraps at labelWidth
// can also set this as a property later to dynamically change width of text
// without changing the size
new Label({
text:"this is a long bunch of text, this is a long bunch of text, this is a long bunch of text",
labelWidth:200
}).center();
END EXAMPLE
EXAMPLE
STYLE = {font:"courier"};
new Label("Hi Courier").center(); // will be courier not arial
STYLE = {text:"YAY!", color:"Red"};
new Label().center().mov(0,100); // will say YAY! in red arial font
new Label("Hello").center().mov(0,200); // will say Hello in red arial
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
text |ZIM VEE| - String for the the text of the label
size - (default 36) the size of the font in pixels
font - (default arial) the font or list of fonts for the text
color - (default "black") color of font (any CSS color)
rollColor - (default color) the rollover color of the font
shadowColor - (default -1) for no shadow - set to any css color to see
shadowBlur - (default 14) if shadow is present
align - ((default "left") text registration point alignment also "center" and "right"
valign - (default "top") vertical registration point alignment alse "middle / center", "bottom"
bold - (default false) set the font to bold - note: fontOptions has been removed as of ZIM Cat
italic - (default false) set the font to italic - note: fontOptions has been removed as of ZIM Cat
variant - (default false) set to true to set the font to "small-caps" - note: fontOptions has been removed as of ZIM Cat
lineWidth - (default false) for no wrapping (use \n) Can set to number for wrap
lineHeight - (default getMeasuredLineHeight) set to number to adjust line height
backing - (default null) a Display object for the backing of the label (eg. Shape, Bitmap, Container, Sprite)
the backing most likely should be centerReg() ie. backing:new Rectangle(200,50,yellow).centerReg()
see ZIM Pizzazz module for a fun set of Shapes like Boomerangs, Ovals, Lightning Bolts, etc.
outlineColor - (default null - or black if outlineWidth set) - the color of the outline of the text
outlineWidth - (default null - or (size*.2) if outlineColor set) - the thickness of the outline of the text
backgroundColor - (default null) set to CSS color to add a rectangular color around the label
The background color will change size to match the text of the label
Note: the backgroundColor is different than a backing which can be any Display Object
and background parameters are ignored if a backing parameter is set
backgroundBorderColor - (default null) the background stroke color
backgroundBorderWidth - (default null) thickness of the background border
corner - (default 0) the round of corner of the background if there is one
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
backgroundDashed - (default null) set to true for dashed background border (if backgroundBorderColor or backgroundBorderWidth set)
padding - (default 10 if backgroundColor set) places the border this amount from text (see paddingHorizontal and paddingVertical)
padding parameters are ignored if there is no backgroundColor set (also ignored if a backing parameter is set)
paddingHorizontal - (default padding) places border out at top bottom
paddingVertical - (default padding) places border out at left and right
shiftHorizontal - (default 0) move the label (CreateJS Text) inside the Label container horizontally
shiftVertical - (default 0) move the label (CreateJS Text) inside the Label container vertically
rollPersist - (default false) set to true to maintain rollover stage as long as mousedown or press is activated (used by Buttons)
labelWidth - (default null) the same as the lineWidth - the text will wrap at the labelWidth (added to match labelHeight)
labelHeight - (default null) the height of the text - setting this will probably alter the font size - so the size parameter is overwritten
for labelHeight to work, the labelWidth must also be set
using labelWidth and labelHeight together allow you to fit as much text into specified width and height dimensions
maxSize - (default null) set to limit the font size when using labelWidth and labelHeight
splitWords - (default false) set to true when lineWidth > 0 to split words at the line width
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setColorRange(color1, color2) - set a color range for label - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
showRollColor(visible) - default true to show roll color (used internally)
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact) - makes a copy with properties such as x, y, etc. also copied
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
label - references the CreateJS Text object of the label
text - references the text property of the CreateJS Text object
size - the font size of the Label (without px)
font - get or set the font of the text
bold - get or set the bold (boolean) of the font
italic - get or set the italic (boolean) of the font
variant - get or set the variant (boolean) of the font (true is "small-caps")
align - get or set the horizontal alignment of the text
valign - get or set the vertical alignment of the text
paddingHorizontal - read-only value for paddingHorizontal of label
note - no padding property - that gets split into paddingHorizontal and paddingVertical
paddingVertical - read-only value for paddingVertical of label
color - gets or sets the label text color
backgroundColor - gets or sets the label background color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the label
for instance, label.setColorRange(blue, pink) then label.colorRange = .5
will set the color of the label to half way between blue and pink
label.animate({color:red}, 1); is a shortcut to animate the colorRange
label.wiggle("colorRange", .5, .2, .5, 1, 5) will wiggle the colorRange
rollColor - gets or sets the label rollover color
labelWidth - the width at which the text wraps
currently does not work well with labelHeight and backgroundColor
labelHeight - setting this and labelWidth will change the font size to fit within the specified dimensions
outlineLabel - reference to the outline CreateJS Text object if there is an outline
backing - access to backing object
background - access to background Rectangle if backgroundColor is set
enabled - default is true - set to false to disable
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+54
zim.Label = function(text, size, font, color, rollColor, shadowColor, shadowBlur, align, valign, bold, italic, variant, lineWidth, lineHeight, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, splitWords, style, group, inherit) {
var sig = "text, size, font, color, rollColor, shadowColor, shadowBlur, align, valign, bold, italic, variant, lineWidth, lineHeight, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, splitWords, style, group, inherit";
var duo; if (duo = zob(zim.Label, arguments, sig, this)) return duo;
z_d("54");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Label";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(text)) text=DS.text!=null?DS.text:"LABEL";
if (zot(size)) size=DS.size!=null?DS.size:36;
if (zot(font)) font=DS.font!=null?DS.font:"arial"; // arial unless manually set
if (zot(color)) color=DS.color!=null?DS.color:"black";
if (zot(bold)) bold=DS.bold!=null?DS.bold:false;
if (zot(italic)) italic=DS.italic!=null?DS.italic:false;
var oa = remember(text, size, font, color, bold, italic);
function remember() {return arguments;}
text = zim.Pick.choose(text);
var emptyText = false;
if (text === "") {
text = " ";
emptyText = true;
}
size = zim.Pick.choose(size);
font = zim.Pick.choose(font);
color = zim.Pick.choose(color);
bold = zim.Pick.choose(bold);
italic = zim.Pick.choose(italic);
if (zot(rollColor)) rollColor=DS.rollColor!=null?DS.rollColor:null;
if (zot(shadowColor) || shadowColor=="ignore") shadowColor=(DS.shadowColor!=null&&shadowColor!="ignore")?DS.shadowColor:-1;
if (zot(shadowBlur) || shadowBlur=="ignore") shadowBlur=(DS.shadowBlur!=null&&shadowBlur!="ignore")?DS.shadowBlur:14;
if (zot(align)) align=DS.align!=null?DS.align:"left";
if (zot(valign)) valign=DS.valign!=null?DS.valign:"top";
if ((!zot(outlineColor) || !zot(DS.outlineColor)) && zot(outlineWidth)) outlineWidth = DS.outlineWidth!=null?DS.outlineWidth:Math.round(size*.2);
if ((!zot(outlineWidth) || !zot(DS.outlineWidth)) && zot(outlineColor)) outlineColor = DS.outlineColor!=null?DS.outlineColor:"#000000";
if (zot(outlineWidth)) outlineWidth = DS.outlineWidth!=null?DS.outlineWidth:0;
if (zot(backgroundColor) || backgroundColor=="ignore") backgroundColor = (DS.backgroundColor!=null&&backgroundColor!="ignore")?DS.backgroundColor:null;
if (zot(padding) || padding=="ignore") padding = (DS.padding!=null&&padding!="ignore")?DS.padding:10;
if (zot(paddingHorizontal)) paddingHorizontal = DS.paddingHorizontal!=null?DS.paddingHorizontal:padding;
if (zot(paddingVertical)) paddingVertical = DS.paddingVertical!=null?DS.paddingVertical:padding;
if (zot(shiftHorizontal)) shiftHorizontal = DS.shiftHorizontal!=null?DS.shiftHorizontal:0;
if (zot(shiftVertical)) shiftVertical = DS.shiftVertical!=null?DS.shiftVertical:0;
if (zot(variant)) variant=DS.variant!=null?DS.variant:false;
if (zot(lineWidth)) lineWidth = DS.lineWidth!=null?DS.lineWidth:null;
if (zot(lineHeight)) lineHeight = DS.lineHeight!=null?DS.lineHeight:null;
if (zot(backing) || backing=="ignore") backing = (DS.backing!=null&&backing!="ignore")?DS.backing.clone():null;
if (zot(rollPersist)) rollPersist = DS.rollPersist!=null?DS.rollPersist:false;
if (DS.labelWidth!=null) lineWidth = DS.labelWidth;
if (!zot(labelWidth)) lineWidth = labelWidth;
if (align == "middle") align = "center";
if (zot(labelHeight)) labelHeight = DS.labelHeight!=null?DS.labelHeight:null;
if (zot(maxSize)) maxSize = DS.maxSize!=null?DS.maxSize:null;
size = maxSize?Math.min(size, maxSize):size;
if (zot(splitWords)) splitWords=DS.splitWords!=null?DS.splitWords:false;
var retina = (typeof zdf!="undefined"&&zdf.retina);
var that = this;
this.mouseChildren = false;
this.paddingVertical = paddingVertical;
this.paddingHorizontal = paddingHorizontal;
var options = [];
options[0] = italic?"italic":"normal";
options[1] = variant?"small-caps":"normal";
options[2] = bold?"bold":"normal";
options[3] = size+"px";
options[4] = font;
var opt = options.join(" ");
var text = String(text);
var obj;
var backingPlaced = false;
var lW = lineWidth;
var lH = labelHeight;
if (zot(backing) && zot(backgroundColor)) {
var hitArea = new createjs.Shape();
that.hitArea = hitArea;
} else {
if (lW) lW = lW-paddingHorizontal*2;
if (lH) lH = lH-paddingVertical*2;
}
function makeLabel(t) {
var o = new createjs.Text(t, opt, color);
o.lineWidth = lW;
o.lineHeight = lineHeight;
return o;
}
obj = makeLabel(text);
if (splitWords && lW > size * 1.2) { // approximate
// measure lines to make sure not going past lineWidth
function testLine(l, w, line) {
var endIndex = Math.ceil(lW/w*line.length);
var start = line.substr(0,endIndex);
var l2 = makeLabel(start);
var w2 = l2.getMeasuredWidth();
if (w2 > lW) {
while (w2 > lW) {
endIndex--;
start = line.substr(0,endIndex)
l2 = makeLabel(start);
w2 = l2.getMeasuredWidth();
}
} else if (w2 < lW) {
while (w2 < lW) {
endIndex++;
start = line.substr(0,endIndex)
l2 = makeLabel(start);
w2 = l2.getMeasuredWidth();
}
endIndex--;
start = line.substr(0,endIndex)
}
var end = line.substr(endIndex, line.length);
return {endIndex:endIndex, start:start, end:end};
}
var metrics = obj.getMetrics();
var wCount = 0;
while (metrics.width > lW && wCount < 1000) {
wCount++;
zim.loop(metrics.lines, function(line, i) {
line = line.replace(/^[\s\t]+/, "");
var l = makeLabel(line);
var w = l.getMeasuredWidth();
if (w > lW) {
var dat = testLine(l, w, line);
metrics.lines[i] = dat.start;
// move extra letters into the next line if there is one
if (metrics.lines.length > i+1) {
dat.end.trim();
metrics.lines[i+1] = dat.end + " " + metrics.lines[i+1];
} else {
metrics.lines.push(dat.end);
}
obj = makeLabel(metrics.lines.join(" "));
metrics = obj.getMetrics();
return false;
}
}); // end line loop
} // end while
} // end split test
this.label = obj;
obj.textAlign = align;
obj.textBaseline = "alphabetic";
if (outlineWidth > 0) {
var obj2 = this.outlineLabel = obj.clone();
obj2.color = outlineColor;
obj2.outline = outlineWidth;
}
if (shadowColor != -1 && shadowBlur > 0) obj.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
this.addChild(obj);
function setBackground() {
that.removeChild(that.background);
that.background = new zim.Rectangle(
that.getBounds().width+paddingHorizontal*2, that.getBounds().height+paddingVertical*2,
backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, null, false
);
zim.center(that.background, that, 0);
that.setBounds(that.background.x, that.background.y, that.background.width, that.background.height);
}
function setSize() {
var b = obj.getBounds();
var by = b.y;
var bh = b.height;
if (lW) { // ZIM CAT 4 patch
var bx = b.x;
var bw = lW;
if (align=="right") {
bx = b.x-lW+b.width;
} else if (align=="center") {
bx = -lW/2;
}
obj.setBounds(bx, by, bw, bh);
b = obj.getBounds();
}
var yAdjust;
if (valign == "baseline") {
yAdjust = b.y;
} else if (valign == "top") {
obj.y = size-size/6;
// if (!retina && obj2) obj2.y = size-size/6;
yAdjust = 0;
} else if (valign == "center" || valign == "middle") {
yAdjust = - b.height / 2;
obj.y = size*.3;
// if (!retina && obj2) obj2.y = size*.3;
} else { // bottom align
yAdjust = -b.height;
}
// if (valign!="baseline" && obj2) obj2.y -= size*.06/(valign=="center"?2:1);
that.setBounds(b.x, yAdjust, DS.width?DS.width-padding*2:b.width, DS.height?DS.height-padding*2:b.height);
if (that.hitArea) that.hitArea.graphics.c().f("black").r(that.getBounds().x, that.getBounds().y, that.getBounds().width, that.getBounds().height);
if (valign == "center" || valign == "middle") {
zim.pos(obj, null, 0);
zim.mov(obj, 0, 1);
}
if (!labelHeight) {
if (backing) {
if (backingPlaced) setBackBounds();
} else if (!zot(backgroundColor)) {
setBackground();
}
}
if (valign != "baseline" && !retina) obj.y += size/32; //32; // backing often on capital letters without descenders - was /16
finalShift();
}
setSize();
if (!zot(backing)) {
if (backing.type == "Pattern") {
that.backing = new zim.Container(that.width+paddingHorizontal*2, that.height+paddingVertical*2, null, null, false).centerReg(null, null, false);
if (shadowColor != -1 && shadowBlur > 0) {
var shadowRect = new zim.Rectangle(that.width+paddingHorizontal*2-2, that.height+paddingVertical-2, "#666", null, null, corner, null, null, false).center(that.backing);
shadowRect.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
var mask = new zim.Rectangle(that.width+paddingHorizontal*2, that.height+paddingVertical*2, backgroundColor, null, null, corner, null, null, false).addTo(that.backing);
backing.centerReg(mask);
backing.setMask(mask);
that.backing.pattern = backing;
} else {
that.backing = backing;
}
that.backing.center(that, 0);
backing = that.backing;
setBackBounds();
backingPlaced = true;
}
function setBackBounds() {
var bb = backing.boundsToGlobal();
var bbb = that.boundsToGlobal(bb, true);
that.setBounds(bbb.x, bbb.y, bbb.width, bbb.height);
}
function finalShift() {
zim.pos(obj, (align=="left"||align=="right")?(backing||that.background?paddingHorizontal:0):null, (valign=="top"||valign=="baseline"||valign=="bottom")?(backing||that.background?paddingVertical:0):null, align=="right", valign=="bottom");
// zim.pos(obj, (align=="left"||align=="right")?0:null, (valign=="top"||valign=="baseline"||valign=="bottom")?0:null, align=="right", valign=="bottom");
obj.x += shiftHorizontal;
obj.y += shiftVertical;
}
finalShift();
function setOutline() {
if (obj2) {
obj2.x = obj.x;
obj2.y = obj.y;
that.addChildAt(obj2,(that.background||that.backing)?1:0);
}
}
setOutline();
Object.defineProperty(that, 'text', {
get: function() {
var t = (obj.text == " " && emptyText) ? "" : obj.text;
return t;
},
set: function(value) {
emptyText = false;
if (value === "") {
value = " ";
emptyText = true;
}
obj.text = String(value);
obj.setBounds(null);
that.setBounds(null);
setSize();
if (obj2) obj2.text = String(value);
if (!zot(lineWidth) && !zot(labelHeight)) {
fitText();
if (obj2) setOutline();
}
}
});
Object.defineProperty(that, 'size', {
get: function() {
return size;
},
set: function(value) {
size = maxSize?Math.min(value, maxSize):value;
options[3] = size + "px";
this.label.font = options.join(" ");
if (obj2) obj2.font = options.join(" ");
obj.setBounds(null);
that.setBounds(null);
setSize();
}
});
Object.defineProperty(that, 'bold', {
get: function() {
return Boolean(this.label.font.match("bold"));
},
set: function(value) {
bold = value;
options[2] = value?"bold":"normal";
this.label.font = options.join(" ");
if (obj2) obj2.font = options.join(" ");
}
});
Object.defineProperty(that, 'italic', {
get: function() {
return Boolean(this.label.font.match("italic"));
},
set: function(value) {
italic = value;
options[0] = value?"italic":"normal";
this.label.font = options.join(" ");
if (obj2) obj2.font = options.join(" ");
}
});
Object.defineProperty(that, 'variant', {
get: function() {
return Boolean(this.label.font.match("small-caps"));
},
set: function(value) {
variant = value;
options[1] = value?"small-caps":"normal";
this.label.font = options.join(" ");
if (obj2) obj2.font = options.join(" ");
}
});
Object.defineProperty(that, 'font', {
get: function() {
return options[4];
},
set: function(value) {
if (zot(value)) return;
font = value;
options[4] = value;
this.label.font = options.join(" ");
if (obj2) obj2.font = options.join(" ");
}
});
Object.defineProperty(that, 'align', {
get: function() {
return align;
},
set: function(value) {
if (zot(value)) return;
align = value;
this.label.textAlign = align;
if (obj2) obj2.textAlign = align;
setSize();
}
});
Object.defineProperty(that, 'valign', {
get: function() {
return valign;
},
set: function(value) {
if (zot(value)) return;
valign = value;
setSize();
}
});
Object.defineProperty(that, 'color', {
get: function() {
return color;
},
set: function(value) {
if (rollColor == color) rollColor = value;
color = value;
obj.color = color;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
var startColor;
var endColor;
this.setColorRange = function(color1, color2) {
if (zot(color2)) {
startColor = that.color;
endColor = color1;
} else if (zot(color1)) {
startColor = that.color;
endColor = color2;
} else {
startColor = color1;
endColor = color2;
}
return that;
};
var _colorRange = 0;
Object.defineProperty(that, 'colorRange', {
get: function() {
return _colorRange;
},
set: function(value) {
_colorRange = value;
if (!zot(startColor) && !zot(endColor)) {
that.color = zim.colorRange(startColor, endColor, value);
}
}
});
Object.defineProperty(that, 'backgroundColor', {
get: function() {
return backgroundColor;
},
set: function(value) {
backgroundColor = value;
if (that.background) {
that.background.color = value;
} else if (that.backing) {
that.backing.color = value;
} else {
setBackground();
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(that, 'outlineColor', {
get: function() {
return outlineColor;
},
set: function(value) {
outlineColor = value;
if (obj2) obj2.color = outlineColor;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(that, 'rollColor', {
get: function() {
return rollColor;
},
set: function(value) {
if (!that.mouseoverEvent && value) setRollColors();
if (value==null && that.mouseoverEvent) removeRollColors();
rollColor = value;
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
obj.color = color;
that.mouseChildren = false;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
this.showRollColor = function(yes) {
if (zot(yes)) yes = true;
if (yes) {
obj.color = rollColor;
} else {
obj.color = color;
}
if (that.stage) that.stage.update();
return that;
};
function setRollColors() {
that.mouseoverEvent = that.on("mouseover", function(e) {if (that.showRollColor) that.showRollColor();});
that.mouseoutEvent = that.on("mouseout", function(e) {if (!that.rollPersist) that.showRollColor(false);});
that.pressupEvent = that.on("pressup", function(e) {if (that.rollPersist) that.showRollColor(false);});
}
function removeRollColors() {
that.off("mouseover", that.mouseoverEvent);
that.off("mouseout", that.mouseoutEvent);
that.off("pressup", that.pressupEvent);
}
if (rollColor) setRollColors();
Object.defineProperty(that, 'labelWidth', {
get: function() {
return lineWidth;
},
set: function(value) {
if (value > 0) {
lineWidth = value;
lW = lineWidth;
if (!zot(backing) || !zot(backgroundColor)) {
if (lW) lW = lW-paddingHorizontal*2;
}
that.label.lineWidth = lW;
if (obj2) obj2.lineWidth = lW;
obj.setBounds(null);
that.setBounds(null);
setSize();
if (labelHeight) fitText();
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
}
});
Object.defineProperty(that, 'labelHeight', {
get: function() {
return labelHeight;
},
set: function(value) {
if (value > 0) {
labelHeight = value;
lH = labelHeight;
if (!zot(backing) || !zot(backgroundColor)) {
if (lH) lH = lH-paddingVertical*2;
}
if (lineWidth) fitText();
that.setBounds(null);
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
}
});
if (!zot(lineWidth) && !zot(labelHeight)) {
fitText();
}
function fitText() {
that.size = 200;
var count = 0;
while(lineHeight < lH / 2 && (that.height > lH || that.width > lW)) {
// while(that.height > labelHeight || that.width > lineWidth) { // ami Aug 2019
count++;
that.size = that.size/2;
if (count>50) break;
}
count = 0;
while(that.height <= lH && that.width <= lW) {
count++;
that.size = Math.ceil(that.size + 1);
if (count>50) break;
}
that.size = that.size - 1;
setOutline();
obj.setBounds(null);
var b = obj.getBounds();
var by = b.y;
var bh = b.height;
if (lH) {
if (valign=="bottom") {
by = b.y-lH+b.height;
} else if (valign=="center") {
by = -lH/2;
}
bh = lH;
}
obj.setBounds(b.x, by, b.width, bh);
if (backing) {
if (backingPlaced) setBackBounds();
} else if (!zot(backgroundColor)) {
setBackground();
}
}
zim.styleTransforms(this, DS);
this.clone = function(exact) {
return that.cloneProps(new zim.Label((exact||!zim.isPick(oa[0]))?that.text:oa[0], (exact||!zim.isPick(oa[1]))?size:oa[1], (exact||!zim.isPick(oa[2]))?font:oa[2], (exact||!zim.isPick(oa[3]))?color:oa[3], rollColor, shadowColor, shadowBlur, align, valign, (exact||!zim.isPick(oa[4]))?bold:oa[4], (exact||!zim.isPick(oa[5]))?italic:oa[5], variant, lineWidth, lineHeight,
!zot(backing)?backing.clone(exact):null, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, splitWords, style, this.group, inherit));
};
};
zim.extend(zim.Label, zim.Container, "clone", "zimContainer");
//-54
/*--
zim.LabelOnPath = function(label, path, percentAngle, percents, showPath, allowToggle, interactive, onTop, style, group, inherit)
LabelOnPath
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a label along a path of a Squiggle or Blob - which can be interactive, fixed, toggled or hidden
A list of percentages for where the letters are can be provided to move around letters
See: https://zimjs.com/explore/labelonpath.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var lop = new LabelOnPath({
label:"Hello World",
// label:new Label({text:"JELLO JIGGLES!", size:50}),
// path:new Blob(),
// path:new Squiggle({
// color:lighter,
// thickness:4,
// points:[[0,75,0,0,-100,200,100,-200],[300,75,0,0,-100,200,100,-200]]
// }).transformPoints("scaleX",2).transformPoints("rotation",0),
percentAngle:100, // default
showPath:false, // default
allowToggle:true, // default
interactive:true, // default
onTop:false // default
}).center();
zog(lop.text)
frame.on("keydown", function () {
// shows percent spacing of letters along path
// could pass [results] in as an array to percents parameter of LabelOnPath
zog(lop.percents.toString());
// uncomment to record the path
// could pass this in as the points parameter to start with a given path
// lop.path.recordPoints(true);
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
label - (default "Label on Path") a String or a ZIM Label
can set any label properties such as color, size, font, etc. on the label passed in
path - (default new Squiggle()) a ZIM Squiggle or ZIM Blob
can set any properties such as color, points, etc. on the shape passed in
percentAngle - (default 100) from 0-100 (or beyond in either direction) as to how much to tilt the letters
percents - (default null) an array of percentage locations of the letters along the line - should match number of letters
showPath - (default true) Boolean to show path at start
allowToggle - (default true) Boolean to allow user to toggle path off and on
interactive - (default true) Boolean to allow user to change path with controls, drag or add and remove points
can also set these individually on the path
onTop - (default false) - Boolean to set path on top when dragged
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
toggle(state) - leave off state to toggle path to opposite state. Use true to hide and false to show - returns object for chaining
hidePath() - hides path - returns object for chaining
showPath() - shows path - returns object for chaining
resize() - if not interactive, call this to update the text on the path - returns object for chaining
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - the name of the class as a String
text - get or set the text on the path
path - read-only access to path - but can manipulate the path
letters - access to ZIM Container of labels used for letters
for instance labels.loop(function (label) {label.color = red;});
or animate as a sequence labels.animate({props:{scale:1.5}, loop:true, rewind:true, sequence:200});
numLetters - how many letters - same as letters.numChildren
percents - access to the array of percents for letter positioning - resize() after changing unless interactive which auto resizes
color - get or set the color of the text
allowToggle - get or set the Boolean to allow toggling the path
interactive - get or set the Boolean to allow interaction with the path
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+54.5
zim.LabelOnPath = function(label, path, percentAngle, percents, showPath, allowToggle, interactive, onTop, style, group, inherit) {
var sig = "label, path, percentAngle, percents, showPath, allowToggle, interactive, onTop, style, group, inherit";
var duo; if (duo = zob(zim.LabelOnPath, arguments, sig, this)) return duo;
z_d("54.5");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "LabelOnPath";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(label)) label = DS.label!=null?DS.label:new zim.Label("Label on Path");
if (zot(path)) path = DS.path!=null?DS.path:new zim.Squiggle({points:[[0,0,0,0,-86,57,86,-57],[300,150,0,0,-133,21,133,-21]]});
if (zot(percentAngle)) percentAngle = DS.percentAngle!=null?DS.percentAngle:100;
if (zot(percents)) percents = DS.percents!=null?DS.percents:null;
if (zot(showPath)) showPath = DS.showPath!=null?DS.showPath:true;
if (zot(allowToggle)) allowToggle = DS.allowToggle!=null?DS.allowToggle:true;
if (zot(interactive)) interactive = DS.interactive!=null?DS.interactive:true;
if (zot(onTop)) onTop = DS.onTop!=null?DS.onTop:false;
var color = label.color;
path.addTo(this);
var that = this;
this.path = path;
this.allowToggle = allowToggle;
path.interactive = interactive;
if (typeof label == "string") label = new zim.Label(label);
var lastAlpha = path.alpha;
if (!showPath) path.alp(0);
path.onTop = onTop;
var letters = this.letters = new zim.Container().addTo(this);
if (!percents) {
percents = [];
for (var i=0; i=0; i--) {
letters.getChildAt(i).dispose();
}
that.numLetters = label.text.length;
for (var i=0; i180?(point.angle-360):point.angle)*percentAngle/100);
}
return this;
};
setText();
this.showPath = function(controls) {
this.toggle(true);
path.toggle(controls);
return this;
};
this.hidePath = function() {
this.toggle(false);
return this;
};
Object.defineProperty(that, 'text', {
get: function() {
return label.text;
},
set: function(value) {
label.text = value;
percents = [];
for (var i=0; i0 && zot(arcBorderColor)) arcBorderColor = "#000000";
else if (zot(arcBorderWidth) && !zot(arcBorderColor)) arcBorderWidth = 2;
arc.graphics.c().f(null).s(arcBorderColor).ss(arcBorderWidth).arc(0,0,radius, (startAngle-90)*Math.PI/180, (startAngle-90+totalAngle)*Math.PI/180);
}
}
makeArc();
if (angles) {
// overwrite totalAngle with given angles
totalAngle = 0;
for (var i=0; ibold - or bolditalic - or italicunderline - can use this with to make a classic underlined link
link
font
note: use NO QUOTES except for single quote with colors if want HTML blue for instance rather than ZIM blue
note: setting groupStyle will make letter from scratch as opposed to building on the submitted label styles
align - (default "center") set to "left", "center" / "middle", "right" for letter registration x positioning
also see lineAlign for alignment of lines
valign - (default "center") set to "top", "center" / "middle", "bottom" for letter registration y positioning
also see lineValign for vertical alignment of lines
letterSpacing - (default 5) - the space between letters
letterSpacing is turned off if the Label has a backgroundColor
to use letterSpacing and a backgroundColor use the backing parameter of Label instead of backgroundColor
or use letterSpacings (see below) to set specific spacings (kerning) on letters
letterSpacings - (default null) - an array of the space between letters each letter
any value here will override the letterSpacing
0 is the index for the space between first and second letter
the length of this should be one less than the number of letters
lineSpacing - (default 5) - the space between lines (not including lineHeight)
lineSpacings - (default null) - an array of the space between lines
any values here will override the lineSpacing
lineHeight - (default null) null will auto set the height. Set to a number to force line heights - if \n or are present in label
lineAlign - (default LEFT or RIGHT for rtl:true) the horizontal alignment of lines if multiple lines - set to LEFT, CENTER/MIDDLE, RIGHT
lineValign - (default BOTTOM) the vertical alignment within lineSpacing if multiple lines - set to TOP, CENTER/MIDDLE, BOTTOM
cache - (default false) set to true to cache each letter - improves performance on animation
rtl - (default false) set to true to reverse letters other than a-zA-Z0-9 and set default lineAlign to RIGHT
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - the name of the class as a String
text - get the text of the original Label
labels - an array of ZIM Label objects for the letters
numLetters - how many letters (same as numChildren)
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+54.57
zim.LabelLetters = function(label, align, valign, letterSpacing, letterSpacings, lineSpacing, lineSpacings, lineHeight, lineAlign, lineValign, cache, rtl, style, group, inherit) {
var sig = "label, align, valign, letterSpacing, letterSpacings, lineSpacing, lineSpacings, lineHeight, lineAlign, lineValign, cache, rtl, style, group, inherit";
var duo; if (duo = zob(zim.LabelLetters, arguments, sig, this)) return duo;
z_d("54.57");
this.group = group;
var DS = style===false?{}:zim.getStyle("LabelLetters", this.group, inherit);
if (zot(label)) label = DS.label != null ? DS.label : new zim.Label("Label Letters");
if (zot(align)) align = DS.align != null ? DS.align : "center";
if (zot(valign)) valign = DS.valign != null ? DS.valign : "center";
if (zot(letterSpacing)) letterSpacing = DS.letterSpacing != null ? DS.letterSpacing : 5;
if (zot(letterSpacings)) letterSpacings = DS.letterSpacings != null ? DS.letterSpacings : null;
if (zot(lineHeight)) lineHeight = DS.lineHeight != null ? DS.lineHeight : null;
if (zot(lineSpacing)) lineSpacing = DS.lineSpacing != null ? DS.lineSpacing : 5;
if (zot(lineSpacings)) lineSpacings = DS.lineSpacings != null ? DS.lineSpacings : null;
if (zot(rtl)) rtl = DS.rtl != null ? DS.rtl : false;
if (zot(lineAlign)) lineAlign = DS.lineAlign != null ? DS.lineAlign : rtl?"right":"left";
if (zot(lineValign)) lineValign = DS.lineValign != null ? DS.lineValign : "bottom";
if (zot(cache)) cache = DS.cache != null ? DS.cache : false;
this.zimContainer_constructor(null, null, null, null, false);
this.type = "LabelLetters";
var that = this;
var letterData = that.letterData = [];
var original;
if (label.type != "Label") {
data = parseHTML(label); // returns {text:text, data:data}
letterData = data.data;
label = new zim.Label(data.text);
} else {
data = parseHTML(label.text);
letterData = data.data;
label.text = data.text;
}
that.text = data.original;
that._color = label.color;
function parseHTML(html) {
var data = [];
// var example = "LabelLetters()
Example: strongemphasisunderline big red verdana the next line"
// "LabelLetters()Example: strong emphasis underlinebig red verdanathe next line"
// "01234567890123456789012345678901234567890123456789012345678901234567890120123456789012"
// "0 1 2 3 4 5 6 7"
// html = "!Roger הגיע בשבילך משהו בדואר Dan אני לומד עברית";
// html = "הגיע בשבילך משהו בדואר.";
if (rtl) {
count = -1;
function insert(data) {
return data.split("").reverse().join("")
}
html = html.replace(/[\u0591-\u07FF]+/ig, insert);
// and there may be tags or LTR characters next to RTL without a space:
html = html.replace(/([^\u0591-\u07FF ])([\u0591-\u07FF])/ig, "$1-!!-$2"); // note the not space
html = html.replace(/([\u0591-\u07FF])([^\u0591-\u07FF ])/ig, "$1-!!-$2"); // note the not space
html = html.replace(/([^\u0591-\u07FF]) ([\u0591-\u07FF])/ig, "$1-!!- -!!-$2");
html = html.replace(/([\u0591-\u07FF]) ([^\u0591-\u07FF])/ig, "$1-!!- -!!-$2");
var sp = html.split(/-!!-/g);
loop(sp, function(ssp, i){
if (ssp.match(/[\u0591-\u07FF]/i)) {
sp[i] = ssp.split(" ").reverse().join(" ");
}
});
html = sp.join("");
}
// normalize tags
html = html.replace(/\n|\r/g," ");
html = html.replace(/||/gi,"");
html = html.replace(/<\/strong>/gi,"");
html = html.replace(/||/gi,"");
html = html.replace(/<\/em>/gi,"");
html = html.replace(/\\n|\\r/g," ");
html = html.replace(/ | | (<\/br>)?/gi," ");
html = html.replace(/]*>/g,
/<(a|i|u|f|br|\/a|\/i|\/u|\/f|b)[^>]*>/g,
/<(b|i|u|f|br|\/b|\/i|\/u|\/f|\/a)[^>]*>/g,
/<(b|i|u|f|br|\/b|\/i|\/u|\/f|a)[^>]*>/g,
/<(b|a|u|f|br|\/b|\/a|\/u|\/f|\/i)[^>]*>/g,
/<(b|a|u|f|br|\/b|\/a|\/u|\/f|i)[^>]*>/g,
/<(b|a|i|f|br|\/b|\/a|\/i|\/f|\/u)[^>]*>/g,
/<(b|a|i|f|br|\/b|\/a|\/i|\/f|u)[^>]*>/g,
/<(b|a|i|u|br|\/b|\/a|\/i|\/u|\/f)[^>]*>/g,
/<(b|a|i|u|br|\/b|\/a|\/i|\/u|f)[^>]*>/g
];
var types = ["b","a","i","u","font"];
var p;
zim.loop(types, function(type, i) {
p = html.replace(regs[i*2],"");
if (type=="font") {
var arr = p.split("");
}
process(arr, type, 0); // 0 for add
p = html.replace(regs[i*2+1],"");
arr = p.split(""+type+">");
process(arr, type, 1); // 1 for remove
});
p = html.replace(/ /gi,"@^#");
p = p.replace(/<(b|a|i|u|f|\/b|\/a|\/i|\/u|\/f)[^>]*>/g,"");
arr = p.split("@^#");
var original = arr.join("\n");
p = arr.join("");
process(arr, "br", 0); // 0 for add
function process(text, type, action) {
if (text.length > 1) {
if ((type=="font" || type=="a") && action==0) {
var length = text[0].length;
zim.loop(text, function(s, i) {
if (i==0) return;
var d = data[length];
if (!d) data[length] = [];
d = data[length] ;
var arr = s.split(">");
if (d[action]) d[action].push(type + " " + arr[0]);
else d[action] = [type + " " + arr[0]];
length += arr[1].length;
});
} else {
text.pop();
var running = 0;
zim.loop(text, function(s) {
running += s.length;
var d = data[running];
if (!d) data[running] = [];
d = data[running];
if (d[action]) d[action].push(type);
else d[action] = [type];
});
}
}
}
// [[adds at index], [removes at index]]
// b,i,u,br,a,font
// var da = [,, [["b","i"]] ,[,["b"]],,,[["br","font color=red size=10 family=courier"]],["i"]],...];
return {text:p, data:data, original:original};
}
that.numLetters = label.text.length;
// NORMALIZE SPACINGS
var letterSpacingsOriginal = !zot(letterSpacings);
if (letterSpacings && !Array.isArray(letterSpacings)) letterSpacings = null;
if (!letterSpacings) {
letterSpacings = [];
for (var i = 0; i < that.numLetters; i++) {
letterSpacings.push(letterSpacing);
}
} else {
for (var i = 0; i < that.numLetters; i++) {
if (zot(letterSpacings[i])) letterSpacings[i] = letterSpacing;
}
}
that.letterSpacings = letterSpacings;
if (lineSpacings && !Array.isArray(lineSpacings)) lineSpacings = null;
if (!lineSpacings) {
lineSpacings = [];
for (var i = 0; i < that.numLetters - 1; i++) {
lineSpacings.push(lineSpacing);
}
} else {
for (var i = 0; i < that.numLetters - 1; i++) {
if (zot(lineSpacings[i])) lineSpacings[i] = lineSpacing;
}
}
that.lineSpacings = lineSpacings;
// LINE CONTROL
that.labels = [];
that.lines = [[]];
var lineWidths = [];
var lineHeights = [];
var linePositionsY = [0];
var lineY = 0;
var lineW = 0;
var lineH = 0;
var lineNum = 0;
var maxW = 0;
// HTML CONTROL
var d = letterData;
var bCheck = false;
var iCheck = false;
var uCheck = false;
var brCheck = false;
var colorCheck = false;
var sizeCheck = false;
var groupCheck = false;
var familyCheck = false;
var originalGroup = label.group;
var urlCheck = false;
var targetCheck = false;
var backgroundColorCheck = false;
var rollBackgroundColorCheck = false;
// ROLLOVER CONTROL
that.rolls = [[]];
for (var i=0; i= 0) bCheck = false;
if (d[i][1].indexOf("i") >= 0) iCheck = false;
if (d[i][1].indexOf("u") >= 0) uCheck = false;
zim.loop(d[i][1], function (item) {
if (item.match(/^font/i)) {
colorCheck = false;
backgroundColorCheck = false;
if (rollBackgroundColorCheck) that.rolls.push([]);
rollBackgroundColorCheck = false;
sizeCheck = false;
familyCheck = false;
groupCheck = false;
return;
}
if (item.match(/^a/i)) {
urlCheck = false;
targetCheck = false;
return;
}
});
}
// start tags
if (d[i][0]) {
if (d[i][0].indexOf("b") >= 0) bCheck = true;
if (d[i][0].indexOf("i") >= 0) iCheck = true;
if (d[i][0].indexOf("u") >= 0) uCheck = true;
brCheck = 0;
zim.loop(d[i][0], function (item) {
if (item=="br") brCheck++;
});
zim.loop(d[i][0], function (item) {
if (item.match(/^font/i)) {
var r = item.match(/ color\s?=\s?(\S*)/i);
if (r) {
colorCheck = r[1];
var ind = zim.colors.indexOf(colorCheck);
if (ind>=0) colorCheck = zim.colorsHex[ind];
colorCheck = colorCheck.replace(/'/g,"");
}
r = item.match(/size\s?=\s?(\S*)/i);
if (r) sizeCheck = r[1];
r = item.match(/backgroundColor\s?=\s?(\S*)/i);
if (r) {
backgroundColorCheck = r[1];
var ind = zim.colors.indexOf(backgroundColorCheck);
if (ind>=0) backgroundColorCheck = zim.colorsHex[ind];
backgroundColorCheck = backgroundColorCheck.replace(/'/g,"");
}
r = item.match(/rollBackgroundColor\s?=\s?(\S*)/i);
if (r) {
rollBackgroundColorCheck = r[1];
var ind = zim.colors.indexOf(rollBackgroundColorCheck);
if (ind>=0) rollBackgroundColorCheck = zim.colorsHex[ind];
rollBackgroundColorCheck = rollBackgroundColorCheck.replace(/'/g,"");
}
r = item.match(/group\s?=\s?(\S*)/i);
if (r) groupCheck = r[1];
r = item.match(/family\s?=\s?(.*)/i);
if (r) {
familyCheck = r[1];
familyCheck = familyCheck.split(/\ssize\s?=|\scolor\s?=|\sgroup\s?=/i)[0];
}
return;
}
if (item.match(/^a/i)) {
var r = item.match(/href\s?=\s?(\S*)/i);
if (r) urlCheck = r[1];
r = item.match(/target\s?=\s?(\S*)/i);
if (r) targetCheck = r[1];
return;
}
});
} // end start tag
} // end all tags
// HANDLE CHECKS AND STORE MAX SIZES
if (groupCheck) {
var letter = new Label({text:label.text[i], group:groupCheck})
} else {
var letter = label.clone();
letter.text = label.text[i];
}
that.labels.push(letter);
if (bCheck) letter.bold = true;
if (iCheck) letter.italic = true;
if (colorCheck) letter.color = colorCheck;
if (backgroundColorCheck) letter.backgroundColor = backgroundColorCheck;
var s = letterSpacingsOriginal?letterSpacings[i]:zot(letter.backgroundColor)?letterSpacings[i]:-.5;
if (rollBackgroundColorCheck) {
letter.rollIndex = that.rolls.length-1;
letter.zrbc = rollBackgroundColorCheck;
letter.zobc = letter.backgroundColor;
that.rolls[letter.rollIndex].push(letter);
letter.expand(0);
letter.on("mouseover", rollOn);
letter.on("mouseout", rollOff);
}
if (urlCheck) {
letter.expand(s,0);
letter.zurl = urlCheck;
letter.ztar = targetCheck;
letter.cur();
letter.on("click", function (e) {
var letter = e.currentTarget;
rollOff(e);
if (!letter.ztar) letter.ztar = "_self";
zgo(letter.zurl, letter.ztar);
});
}
if (sizeCheck) letter.size = sizeCheck;
if (familyCheck) letter.font = familyCheck;
if (brCheck) {
lineY += (zot(lineHeight)?lineH:lineHeight) + lineSpacings[lineNum];
linePositionsY.push(lineY);
lineHeights.push(zot(lineHeight)?lineH:lineHeight);
lineWidths.push(lineW);
maxW = Math.max(maxW, lineW);
}
if (brCheck) {
if (brCheck > 1) {
zim.loop(brCheck-1, function (bi) {
that.lines.push([]);
lineY += (zot(lineHeight)?lineH:lineHeight) + lineSpacings[lineNum];
linePositionsY.push(lineY);
lineHeights.push(zot(lineHeight)?lineH:lineHeight);
lineWidths.push(0);
lineNum++;
});
}
lineH = 0;
lineW = 0;
that.lines.push([]);
lineNum++;
}
lineW += letter.width + s;
lineH = Math.max(lineH, letter.height);
if (i==that.numLetters-1) {
lineWidths.push(lineW);
lineHeights.push(lineH);
maxW = Math.max(maxW, lineW);
}
that.lines[lineNum].push(letter);
if (uCheck) letter.underline = new zim.Line(letter.width+s+1,1,letter.color).center(letter,this).mov(0,letter.height/2);
} // end checks
// ROLL FUNCTIONS
function rollOn(e) {
var letter = e.currentTarget;
var rolls = that.rolls[letter.rollIndex]
zim.loop(rolls, function (l) {
l.backgroundColor = letter.zrbc;
})
if (letter.stage) letter.stage.update();
}
function rollOff(e) {
var letter = e.currentTarget;
var rolls = that.rolls[letter.rollIndex]
zim.loop(rolls, function (l) {
l.backgroundColor = letter.zobc;
})
if (letter.stage) letter.stage.update();
}
// LOOP THROUGH LINES AND APPLY POSITIONS
var count = 0;
for (var j=0; j 0) {
b.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
// assumes center reg
b.x = width / 2;
b.y = height / 2;
}
}
that.addChild(that.backing);
if (borderWidth) {
that.border = new zim.Rectangle(width, height, "rgba(0,0,0,0)", borderColor, borderWidth, corner, dashed, null, false);
that.addChild(that.border);
}
function setPattern(type, pattern) {
that[type] = new zim.Container(width, height, null, null, false).centerReg(null, null, false);
if (shadowColor != -1 && shadowBlur > 0) {
var shadowRect = new zim.Rectangle(width-2, height-2, "#666", null, null, corner, null, null, false).center(that[type]);
shadowRect.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
var mask = that[type].mask = new zim.Rectangle(width, height, type.indexOf("roll")>=0?rollBackgroundColor:backgroundColor, null, null, corner, null, null, false).addTo(that[type]);
pattern.centerReg(mask);
pattern.setMask(mask.shape);
that[type].pattern = pattern;
return that[type];
}
//~~~~~~~~~~~~~ ICONS
that.icon = zot(icon)?(DS.icon!=null?DS.icon.clone():null):icon;
that.rollIcon = zot(rollIcon)?(DS.rollIcon!=null?DS.rollIcon.clone():null):rollIcon;
that.waitIcon = zot(waitIcon)?(DS.waitIcon!=null?DS.waitIcon.clone():null):waitIcon;
that.rollWaitIcon = zot(rollWaitIcon)?(DS.rollWaitIcon!=null?DS.rollWaitIcon.clone():null):rollWaitIcon;
that.toggleIcon = zot(toggleIcon)?(DS.toggleIcon!=null?DS.toggleIcon.clone():null):toggleIcon;
that.rollToggleIcon = zot(rollToggleIcon)?(DS.rollToggleIcon!=null?DS.rollToggleIcon.clone():null):rollToggleIcon;
var iconTypes = ["icon", "rollIcon", "toggleIcon", "rollToggleIcon", "waitIcon", "rollWaitIcon"];
for (var i=0; i 0) { // add an overlay
var gr = new createjs.Shape();
gr.graphics.lf(["rgba(255,255,255,"+gradient+")","rgba(0,0,0,"+gradient+")"], [0, 1], 0, 0, 0, height-borderWidth);
gr.graphics.rc(borderWidth/2, borderWidth/2, width-borderWidth, height-borderWidth, corner[0], corner[1], corner[2], corner[3]);
this.addChild(gr);
}
if (gloss > 0) { // add an overlay
var gl = new createjs.Shape();
gl.graphics.f("rgba(255,255,255,"+gloss+")");
gl.graphics.rc(borderWidth/2, borderWidth/2, width-borderWidth, (height-borderWidth)/2, corner[0], corner[1], 0, 0);
gl.graphics.f("rgba(0,0,0,"+gloss+")");
gl.graphics.rc(borderWidth/2, height/2, width-borderWidth, (height-borderWidth)/2, 0, 0, corner[2], corner[3]);
this.addChild(gl);
}
//~~~~~~~~~~~~~ HITAREA AND LABEL
var hitArea;
var rect;
if (hitPadding > 0) makeHitArea();
function makeHitArea() {
rect = new createjs.Shape();
rect.graphics.f("#000").r(-hitPadding,-hitPadding,width+hitPadding*2,height+hitPadding*2);
that.hitArea = hitArea = rect;
}
this.addChild(label);
label.center(this);
// label.y+=(typeof zdf!="undefined" && zdf.retina!=true)?1:0;
label.y+=1;
this.label = label;
zim.pos(label, (align=="left"||align=="right")?indentHorizontal:null, (valign=="top"||valign=="bottom")?indentVertical:null, align=="right", valign=="bottom");
//~~~~~~~~~~~~~ TOGGLE STATE
this.toggled = false;
if (toggleOkay) {
var originalText = label.text;
var originalColor = label.color;
var originalRollColor = label.rollColor;
this.on(toggleEvent, function() {
that.toggled = !that.toggled;
setToggled();
});
}
function setToggled() {
if (that.toggled) {
if (!zot(toggle)) that.label.text = toggle===true?originalText:toggle;
if (!zot(toggleColor)) that.label.color = toggleColor;
if (!zot(rollToggleColor)) that.label.rollColor = rollToggleColor;
// for toggle - may start in rollover or could be manually called
if (that.rolled) {
if (that.rollToggleBacking) changeObject("rollToggleBacking", that.rollToggleBacking);
else if (that.toggleBacking) changeObject("toggleBacking", that.toggleBacking);
if (that.rollToggleIcon) changeObject("rollToggleIcon", that.rollToggleIcon);
else if (that.toggleIcon) changeObject("toggleIcon", that.toggleIcon);
if (zot(backing) && zot(that.rollToggleBacking)) that.backing.color = rollToggleBackgroundColor;
} else {
if (that.toggleBacking) changeObject("toggleBacking", that.toggleBacking);
if (that.toggleIcon) changeObject("toggleIcon", that.toggleIcon);
if (zot(backing)) that.backing.color = toggleBackgroundColor;
}
} else {
that.label.color = originalColor;
that.label.rollColor = originalRollColor;
that.label.text = originalText;
setOriginalObjects();
}
if (that.stage) that.stage.update();
}
function setOriginalObjects() {
if (that.rolled) {
if (zot(backing) && !that.rollBacking) that.backing.color = rollBackgroundColor;
if (that.rollBacking) changeObject("rollBacking", that.rollBacking);
else if (that.backing) changeObject("backing", that.backing);
if (that.rollIcon) changeObject("rollIcon", that.rollIcon);
else if (that.icon) changeObject("icon", that.icon);
else changeObject("icon", null);
} else {
if (zot(backing)) that.backing.color = backgroundColor;
if (that.backing) changeObject("backing", that.backing);
if (that.icon) changeObject("icon", that.icon);
else changeObject("icon", null);
}
}
this.toggle = function(state) {
if (!toggleOkay) {
if (zon) zogy("Button() - can't toggle with wait parameters provided");
return that;
}
if (zot(state)) {
that.toggled = !that.toggled;
} else {
that.toggled = state;
}
setToggled();
return that;
};
//~~~~~~~~~~~~~ WAIT STATE
var pressCheck = false;
that.waiting = false;
var willBeWaiting = false;
var waitTimeout;
var waitStartText;
// var waitStartBackgroundColor;
var waitStartTextBackgroundColor = that.label.color;
var waitStartRollTextBackgroundColor = that.label.rollColor;
var waitStartEnabled;
var waitModalEvent;
var waitEvent = this.on("mousedown", function() {
pressCheck=true;
doWait();
});
function doWait() {
if ((!zot(wait) || !zot(waitBacking) || !zot(rollWaitBacking)) && !that.waiting) {
willBeWaiting = true;
if (zot(waitEnabled)) waitEnabled = true;
if (waitModal) waitModalEvent = that.stage.on("stagemousedown", function(e) {
if (!that.hitTestPoint(e.stageX/zim.scaX, e.stageY/zim.scaY)) that.clearWait();
}, null, true); // run only once
// wait before setting the waiting property so first click is not a waiting
setTimeout(function(){that.waiting = true;}, 50);
// set button to waiting state
waitStartText = label.text;
if (!zot(waitColor)) that.label.color = waitColor;
if (!zot(rollWaitColor)) that.label.rollColor = rollWaitColor;
waitStartEnabled = that.enabled;
if (!waitEnabled && that.enabled) that.enabled = false;
if (!zot(wait)) that.label.text = wait;
if (that.rolled) {
if (zot(backing) && !that.rollWaitBacking) that.backing.color = rollWaitBackgroundColor;
if (that.rollWaitBacking) changeObject("rollWaitBacking", that.rollWaitBacking);
else if (that.waitBacking) changeObject("waitBacking", that.waitBacking);
if (that.rollWaitIcon) changeObject("rollWaitIcon", that.rollWaitIcon);
else if (that.waitIcon) changeObject("waitIcon", that.waitIcon);
} else {
if (zot(backing) && !that.waitBacking) that.backing.color = waitBackgroundColor;
if (that.waitBacking) changeObject("waitBacking", that.waitBacking);
if (that.waitIcon) changeObject("waitIcon", that.waitIcon);
}
if (zot(waitTime)) waitTime = timeType=="s"?5:5000; // 5 seconds
if (waitTimeout) waitTimeout.clear();
waitTimeout = zim.timeout(waitTime, function() {
// set button to proper text, icon, backing, colors, etc.
if (!that.enabled) that.enabled = waitStartEnabled;
that.clearWait();
that.dispatchEvent("waited");
});
if (that.stage) that.stage.update();
}
}
this.wait = function() {
doWait();
};
this.clearWait = function() {
if (!waitTimeout) return that;
if (waitModalEvent) that.stage.off("stagemousedown", waitModalEvent);
waitTimeout.clear();
that.label.text = waitStartText;
setOriginalObjects();
that.label.color = waitStartTextBackgroundColor;
that.label.rollColor = waitStartRollTextBackgroundColor;
setTimeout(function(){that.waiting = false;}, 55); // give time for first click to see not waiting yet
willBeWaiting = false;
if (that.stage) that.stage.update();
return that;
};
this.removeWait = function() {
that.clearWait();
wait = null;
that.waitBacking = null;
that.rollWaitBacking = null;
that.off("mousedown", waitEvent);
return that;
};
//~~~~~~~~~~~~~ INTERACTION
this.on("pressup", function(){
pressCheck=false;
if (that.rollPersist && !reallyOn) removeRoll();
});
// visually swap button backing or icon
// on clicks if wait or toggle and on mouseover and mouseout
// note - icon will be removed if newObject is null
// BUT - backing will be ignored if newObject is null
// so these act slightly differently!
function changeObject(type, newObject) {
if (type.indexOf("con")>=0) { // icon
for (var i=0; i=0?that.numChildren-1:0);
if (that.stage) that.stage.update();
}
if (newObject) {
if (zot(backing) && type == "backing") backing = newObject;
if (newObject.type == "Pattern") newObject = setPattern(type, newObject);
that[type] = newObject;
that[type].x = width/2;
that[type].y = height/2;
} else {
that[type] = null;
}
return that;
}
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function(exact) {
var but = new zim.Button(
width, height, label.clone(),
(exact||!zim.isPick(oa[0]))?backgroundColor :oa[0],
(exact||!zim.isPick(oa[1]))?rollBackgroundColor :oa[1],
(exact||!zim.isPick(oa[2]))?color :oa[2],
(exact||!zim.isPick(oa[3]))?rollColor :oa[3],
originalBorderColor, borderRollColor, originalBorderWidth, corner, shadowColor, shadowBlur, hitPadding, gradient, gloss, dashed,
!zot(backing)?that.backing.clone():null,
!zot(rollBacking)?that.rollBacking.clone():null,
rollPersist,
!zot(icon)?icon.clone():null, !zot(rollIcon)?rollIcon.clone():null,
toggle, toggleBackgroundColor, rollToggleBackgroundColor, toggleColor, rollToggleColor,
!zot(toggleBacking)?toggleBacking.clone():null,
!zot(rollToggleBacking)?rollToggleBacking.clone():null,
!zot(toggleIcon)?toggleIcon.clone():null,
!zot(rollToggleIcon)?rollToggleIcon.clone():null,
toggleEvent,
wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal, waitEnabled,
!zot(waitBacking)?waitBacking.clone():null,
!zot(rollWaitBacking)?rollWaitBacking.clone():null,
!zot(waitIcon)?waitIcon.clone():null,
!zot(rollWaitIcon)?rollWaitIcon.clone():null,
align, valign, indent, indentHorizontal, indentVertical,
style,
this.group,
inherit // added in ZIM Cat 03 - not sure if it was missing on purpose
);
return that.cloneProps(but);
};
this.doDispose = function(a,b,disposing) {
if (that.icon) that.icon.dispose();
if (that.rollIcon) that.rollIcon.dispose();
if (that.waitIcon) that.waitIcon.dispose();
if (that.rollWaitIcon) that.rollWaitIcon.dispose();
if (that.toggleIcon) that.toggleIcon.dispose();
if (that.rollToggleIcon) that.rollToggleIcon.dispose();
that.icon = that.rollIcon = that.waitIcon = that.rollWaitIcon = that.toggleIcon = that.rollToggleIcon = null;
if (!disposing) this.zimContainer_dispose(true);
return true;
}
};
zim.extend(zim.Button, zim.Container, ["clone", "dispose"], "zimContainer", false);
zim.Button.prototype.dispose = function(disposing) {return this.doDispose(null,null,disposing);};
//-55
/*--
zim.CheckBox = function(size, label, startChecked, color, backgroundColor, borderColor, borderWidth, corner, margin, indicatorType, indicatorColor, tap, style, group, inherit)
CheckBox
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A checkbox that when pressed toggles the check and a checked property.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var checkBox = new CheckBox(50, "TEST");
checkBox.center();
checkBox.on("change", function() {
zog(checkBox.checked); // will be true then false, etc.
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
size - (default 60) size in pixels (always square)
label - (default null) ZIM Label object - or String to make a default label (black)
startChecked - (default false) an initial parameter to set checked if true
color - (default "#111") the text color of the label
backgroundColor - (default "rgba(255,255,255,.8)") the background color of the box
borderColor - (default "#111") the color of the border
borderWidth - (default size/10) thickness of the border
corner - (default 0) the round of the corner
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
margin - (default 10) is on outside of box so clicking or pressing is easier
indicatorType - (default check) could be square (box) or x
indicatorColor - (default borderColor or black if no border) the color of the indicator
tap - (default false) set to true to tap to activate CheckBox rather than mousedown or click
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setChecked(Boolean) - defaults to true to set button checked (or use checked property)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
checked - gets or sets the check of the box
label - gives access to the label
text - the text of the label
box - the Rectangle of the checkBox
box2 - the border Rectangle of the checkBox
indicator - gives access to the check mark ie. indicator.sca(.8);
indicatorColor - get or set the color of the indicator
enabled - default is true - set to false to disable
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "change" event when pressed on but not when the checked property is set
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+56
zim.CheckBox = function(size, label, startChecked, color, backgroundColor, borderColor, borderWidth, corner, margin, indicatorType, indicatorColor, tap, style, group, inherit) {
var sig = "size, label, startChecked, color, backgroundColor, borderColor, borderWidth, corner, margin, indicatorType, indicatorColor, tap, style, group, inherit";
var duo; if (duo = zob(zim.CheckBox, arguments, sig, this)) return duo;
z_d("56");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "CheckBox";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(size)) size = DS.size!=null?DS.size:60;
if (zot(label)) label = DS.label!=null?DS.label:null;
if (zot(startChecked)) startChecked = DS.startChecked!=null?DS.startChecked:false;
var myChecked = startChecked;
if (zot(color)) color = DS.color!=null?DS.color:"#111";
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"rgba(255,255,255,.8)";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"#111";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:size/10;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = size/10;
if (zot(corner)) corner=DS.corner!=null?DS.corner:0;
if (typeof label === "string" || typeof label === "number") label = new zim.Label({
text:label, size:size*5/6, color:color, valign:"center",
backing:"ignore", shadowColor:"ignore", shadowBlur:"ignore", padding:"ignore", backgroundColor:"ignore",
style:style, group:this.group
});
if (zot(margin)) margin = DS.margin!=null?DS.margin:size/5;
if (indicatorType != "box" && indicatorType != "square" && indicatorType != "x") indicatorType = DS.indicatorType!=null?DS.indicatorType:"check";
if (zot(indicatorColor)) indicatorColor = DS.indicatorColor!=null?DS.indicatorColor:borderWidth>0?borderColor:"black";
this.setBounds(-margin, -margin, size+margin*2, size+margin*2);
if (zot(tap)) tap = DS.tap!=null?DS.tap:false;
var that = this;
this.cursor = "pointer";
var box = this.box = new zim.Rectangle(size, size, backgroundColor, null, null, corner);
var box2 = this.box2 = new zim.Rectangle(size*5/7, size*5/7, "rgba(0,0,0,0)", borderColor, borderWidth, corner);
box2.x = size/7; box2.y = size/7;
this.addChild(box, box2);
var fullWidth = size;
if (label) {
label.center(that);
label.x = that.getBounds().width;
this.label = label;
this.setBounds(-margin, -margin, size+margin*3+label.getBounds().width, Math.max(size+margin*2, label.getBounds().height));
fullWidth = label.x + label.width;
}
var backing = new zim.Shape({style:false});
var g = backing.graphics;
g.f("rgba(0,0,0,.01)").r(
this.getBounds().x,
this.getBounds().y,
fullWidth+(margin*2),
this.getBounds().height
);
this.hitArea = backing;
// hitArea will stop rollovers on labels but oh well
var check = new zim.Shape({style:false});
var g2 = check.graphics;
if (indicatorType == "check") {
g2.f(indicatorColor).p("AnQAdICBiaIEEDZIF8nfICfB4In/KPg"); // width about 90 reg in middle
} else if (indicatorType == "box" || indicatorType == "square") {
g2.f(indicatorColor).dr(-35,-35,70,70);
} else { // x
g2.f(indicatorColor).p("AmJEVIEUkTIkXkWIB4h5IEWEYIETkTIB4B3IkTESIEQERIh4B4IkRkRIkSEVg"); // width about 90 reg in middle
}
var cW = 95;
check.setBounds(-cW/2, -cW/2, cW, cW);
var scale = size/(cW+66);
check.scaleX = check.scaleY = scale;
check.alpha = .9;
check.x = size/2;
check.y = size/2;
if (myChecked) this.addChild(check);
if (tap) {
this.tap(toggleCheck);
} else {
this.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", toggleCheck);
}
Object.defineProperty(that, 'checked', {
get: function() {
return myChecked;
},
set: function(value) {
that.setChecked(value);
}
});
this.toggle = function(type) {
if (zot(type)) type = !myChecked;
that.setChecked(type);
};
Object.defineProperty(that, 'toggled', {
get: function() {
return myChecked;
},
set: function(value) {
that.setChecked(value);
}
});
Object.defineProperty(that, 'text', {
get: function() {
if (label) return label.text;
return null;
},
set: function(value) {
if (label) {
label.text = value;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
}
});
Object.defineProperty(check, 'indicatorColor', {
get: function() {
return indicatorColor;
},
set: function(value) {
if (myChecked) {that.removeChild(check);}
check = new createjs.Shape();
g2 = check.graphics;
indicatorColor = value;
g2.f(indicatorColor).p("AnQAdICBiaIEEDZIF8nfICfB4In/KPg");
check.scaleX = check.scaleY = scale;
check.alpha = .9;
check.x = size/2;
check.y = size/2;
if (myChecked) that.addChild(check);
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(that, 'indicator', {
get: function() {
return check;
},
set: function(value) {
zog("ZIM CheckBox - check is read only");
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
}
});
function toggleCheck(e) {
myChecked = !myChecked;
that.setChecked(myChecked);
that.dispatchEvent("change");
}
this.setChecked = function(value) {
if (zot(value)) value = true;
myChecked = value;
if (myChecked) {
that.addChild(check);
} else {
that.removeChild(check);
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
return that;
};
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.CheckBox(size, label?label.clone():"", startChecked, color, backgroundColor, borderColor, borderWidth, corner, margin, indicatorType, indicatorColor, tap, style, this.group, inherit));
};
};
zim.extend(zim.CheckBox, zim.Container, "clone", "zimContainer", false);
//-56
/*--
zim.RadioButtons = function(size, buttons, vertical, color, backgroundColor, spacing, margin, always, indicatorColor, style, group, inherit)
RadioButtons
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A radio button set that lets you pick from choices.
Radio buttons can display radio buttons vertically (default) or horizontally.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var radioButtons = new RadioButtons(50, ["ONE", "TWO", "THREE"]);
radioButtons.center();
radioButtons.on("change", function() {
zog(radioButtons.text); // will be ONE, TWO or THREE
zog(radioButtons.selectedIndex); // will be 0, 1, or 2
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
size - (default 60) in pixels
buttons - an array of button data objects as follows:
[{label:ZIM Label or text, id:optional id, selected:optional Boolean}, {etc...}]
or just a list of labels for default labels ["hi", "bye", "what!"]
vertical - (default true) displays radio buttons vertically - set to false to display horizontally
color - (default "#111") the text color of the label
backgroundColor - (default "rgba(255,255,255,.8)") the background color of the circle
borderColor - (default "#111") the color of the border
borderWidth - (default size/9) thickness of the border
spacing - (size*.2 for vertical and size for horizontal) the space between radio button objects
margin - (size/5) the space around the radio button itself
always - (default false) if set true, cannot click on selection to unselect it
indicatorColor - (default borderColor or black) the color of the indicator
selectedIndex - (default 0) - set the selectedIndex at start
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setSelected(num) - sets the selected index (or use selectedIndex) -1 is default (none)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selected - gets the selected object - selected.label, selected.id, etc.
selectedIndex - gets or sets the selected index of the buttons
label - current selected label object
text - current selected label text
id - current selected id
buttons - an array of button Container objects holding the shape and label (note - different than buttons parameter)
labels - an array of the ZIM Label objects. labels[0].text = "YUM"; labels[2].y -= 10;
indicators - an array of the zim Shape dot objects. indicators[0].color = "yellow";
enabled - default is true - set to false to disable
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "change" event when pressed but not when selectedIndex is set
then ask for the properties above for info
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+57
zim.RadioButtons = function(size, buttons, vertical, color, backgroundColor, borderColor, borderWidth, spacing, margin, always, indicatorColor, selectedIndex, style, group, inherit) {
var sig = "size, buttons, vertical, color, backgroundColor, borderColor, borderWidth, spacing, margin, always, indicatorColor, selectedIndex, style, group, inherit";
var duo; if (duo = zob(zim.RadioButtons, arguments, sig, this)) return duo;
z_d("57");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "RadioButtons";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(size)) size = DS.size!=null?DS.size:60;
size = Math.max(5, size);
if (zot(buttons)) buttons = DS.buttons!=null?DS.buttons:["A", "B", "C"];
if (zot(vertical)) vertical = DS.vertical!=null?DS.vertical:true;
if (zot(color)) color = DS.color!=null?DS.color:"#111";
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"rgba(255,255,255,.8)";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"#111";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:size/9;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = size/10;
if (zot(spacing)) spacing = (vertical) ? DS.spacing!=null?DS.spacing:size*.2 : DS.spacing!=null?DS.spacing:size;
if (zot(margin)) margin = DS.margin!=null?DS.margin:size/5;
if (zot(always)) always = DS.always!=null?DS.always:false;
if (zot(indicatorColor)) indicatorColor = DS.indicatorColor!=null?DS.indicatorColor:borderWidth>0?borderColor:"black";
var that = this;
this.cursor = "pointer";
this.labels = [];
this.indicators = [];
var currentObject; // reference to the current data object
if (typeof buttons == "string") {
// convert to buttons object literal (for cloning)
var bString = buttons;
buttons = [];
for (var i=0; i=0; i--) {
data = buttons[i];
if (data.selected && data.selected === true) {
if (!selectedCheck) {
selectedCheck = true; // first item marked selected
that.id = data.id;
} else {
data.selected = "false"; // turn off selected
}
}
}
buttonContainer.removeAllChildren();
that.buttons = [];
var but; var currentLocation = 0;
for (var i=0; i= 0) {
but = buttonContainer.getChildAt(value);
var lastIndex = -2;
if (currentObject) lastIndex = currentObject.index;
currentObject = but.obj;
}
if (value == -1 || lastIndex == currentObject.index) {
currentObject = null;
that.id = null;
that.label = null;
that.text = "";
} else {
but.addChild(but.check);
that.id = currentObject.id;
that.label = currentObject.label;
if (that.label) that.text = that.label.text;
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
return that;
};
// getter setter methods
Object.defineProperty(that, 'selected', {
get: function() {
return currentObject;
},
set: function(value) {
zog("ZIM RadioButton - selected is read only");
}
});
Object.defineProperty(that, 'selectedIndex', {
get: function() {
return (currentObject) ? currentObject.index : -1;
},
set: function(value) {
var index = value;
if (always) {if (that.selectedIndex == index) return;}
that.setSelected(index);
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
}
});
if (zot(selectedIndex)) selectedIndex=DS.selectedIndex!=null?DS.selectedIndex:0;
that.selectedIndex = selectedIndex;
zim.styleTransforms(this, DS);
this.clone = function() {
var buttonsCopy = zim.copy(buttons);
for (var i=0; i 0) {
this.background.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
if (label) {
this.addChild(label);
label.x = width + 2 + margin + borderWidth;
label.y = height/2;
this.label = label;
this.setBounds(-margin, -margin, width+margin*3+borderWidth+label.getBounds().width, Math.max(height+margin*2, label.getBounds().height));
}
if (labelLeft) {
this.addChild(labelLeft);
labelLeft.x = 0;
that.background.x += labelLeft.width + 3 + margin + borderWidth;
that.label.x += labelLeft.width + 3 + margin + borderWidth;
labelLeft.y = height/2;
this.labelLeft = labelLeft;
this.setBounds(-margin, -margin, that.getBounds().width+labelLeft.width + 3 + margin + borderWidth, that.getBounds().height);
}
this.expand(zim.mobile()?20:10);
this.tap(function (e) {
if (labelLeft) {
var point = that.localToGlobal(labelLeft.width+3+margin+borderWidth+width/2, 0);
if ((e.stageX/zim.scaX < (point.x-width/2) && !_toggled) || (e.stageX/zim.scaX >= (point.x+width/2) && _toggled)) return;
}
_toggled = !_toggled;
setToggle();
that.dispatchEvent("change");
}, zim.mobile()?20:10);
var swipe = new zim.Swipe(this, 20, timeType=="s"?.2:200);
swipe.on("swipe", function (e) {
if (e.swipeX==0) {
return;
} else if (e.swipeX==1 && _toggled) {
return;
} else if (e.swipeX==-1 && !_toggled) {
return;
}
_toggled = !_toggled;
setToggle();
that.dispatchEvent("change");
});
function setToggle(immediate){
var oldX = that.indicator.x;
var t = time;
if (immediate===true) t = 0;
if (indicatorType=="rectangle" || indicatorType=="square") {
that.indicator.pos(height*.2, null, _toggled);
if (time>0) that.indicator.animate({props:{x:oldX}, from:true, time:t});
} else {
that.indicator.pos(height*.175, null, _toggled);
if (time>0) that.indicator.animate({props:{x:oldX}, from:true, time:t});
}
that.background.color = _toggled?toggleBackgroundColor:backgroundColor;
that.text = _toggled?(that.label?that.label.text:"on"):(that.labelLeft?that.labelLeft.text:"off");
if (that.zimAccessibility) {
var string = "Toggle set to " + (_toggled?(that.label?that.label.text+".":"on."):(that.labelLeft?that.labelLeft.text+".":"off."));
setTimeout(function() {that.zimAccessibility.talk(string);}, 50);
}
}
Object.defineProperty(that, 'textLeft', {
get: function() {
if (labelLeft) return labelLeft.text;
return null;
},
set: function(value) {
if (labelLeft) {
labelLeft.text = value;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
}
});
that.toggle = function(state, immediate) {
var lastToggle = _toggled;
if (zot(state)) state = true;
_toggled = state;
if (lastToggle != _toggled) setToggle(immediate);
return that;
};
that.text = _toggled?(that.label?that.label.text:"on"):(that.labelLeft?that.labelLeft.text:"off");
Object.defineProperty(that, 'toggled', {
get: function() {
return _toggled;
},
set: function(value) {
that.toggle(value);
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
}
});
if (style !== false) zim.styleTransforms(this, DS);
this.clone = function () {
return that.cloneProps(new zim.Toggle(width, height, label ? label.clone() : "", startToggled, backgroundColor, margin, indicatorType, indicatorColor, tap, toggleBackgroundColor, color, borderColor, borderWidth, corner, indicatorCorner, shadowColor, shadowBlur, time, labelLeft ? labelLeft.clone() : "", style, this.group, inherit));
};
};
zim.extend(zim.Toggle, zim.Container, "clone", "zimContainer", false);
//-57.5
/*--
zim.Tip = function(text, align, valign, margin, marginH, marginV, outside, target, size, font, color, rollColor, shadowColor, shadowBlur, textAlign, textValign, lineWidth, lineHeight, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, bold, italic, variant, splitWords, style, group, inherit)
Tip
zim class - extends a a zim.Label which extends a zim.Container which extends a createjs.Container
DESCRIPTION
A Tip() can be used to show some extra information - the tip disappears after an amount of time
Tip has easy positioning along the inside edges or the outside edges of a target.
NOTE: Tip places the tip on the stage when the show() method is called
You can reposition with .mov() etc. if desired
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
new Tip("Press Circle").show(1); // wait one second and show tip at 40 pixels from bottom right
var circle = new Circle().center().tap(function () {
circleTip.show();
});
var circleTip = new Tip({
text:"This is a default ZIM Circle",
backgroundColor:white,
color:black,
outside:true, // outside the circle
target:circle,
align:"center",
valign:"bottom",
margin:14,
corner:0,
size:20
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
text - (default "Here's a tip!") String for the the text of the tip
align - (default "right") the horizontal position of the tip ("left", "center"/"middle", "right")
valign - (default "bottom") the vertical position of the tip ("top", "center"/"middle", "bottom")
margin - (default 40) distance from side (unless centered) in pixels
marginH - (default margin) distance from horizontal edges
marginV - (default margin) distance from vertical edges
outside - (default false) set to true to place Tip on outside of container
target - (default zdf's stage) tip is placed on stage relative to container
** the rest are parameters for a Label (align and valign are set as textAlign and textValign)
size - (default 36) the size of the font in pixels
font - (default arial) the font or list of fonts for the text
color - (default "black") color of font (any CSS color)
rollColor - (default color) the rollover color of the font
shadowColor - (default "rgba(0,0,0,.3)") set to -1 for no shadow - set to any css color to see
shadowBlur - (default 1) if shadow is present
textAlign - ((default "left") text registration point alignment also "center" and "right"
textValign - (default "center") vertical registration point alignment alse "middle / center", "bottom"
lineWidth - (default false) for no wrapping (use \n) Can set to number for wrap
lineHeight - (default getMeasuredLineHeight) set to number to adjust line height
fontOptions - (default null) css VALUES as a single string for font-style font-variant font-weight
eg. "italic bold small-caps" or just "italic", etc.
backing - (default null) a Display object for the backing of the label (eg. Shape, Bitmap, Container, Sprite)
see ZIM Pizzazz module for a fun set of Shapes like Boomerangs, Ovals, Lightning Bolts, etc.
outlineColor - (default null - or black if outlineWidth set) - the color of the outline of the text
outlineWidth - (default null - or (size*.2) if outlineColor set) - the thickness of the outline of the text
backgroundColor - (default null) set to CSS color to add a rectangular color around the label
The background color will change size to match the text of the label
Note: the backgroundColor is different than a backing which can be any Display Object
and background parameters are ignored if a backing parameter is set
backgroundBorderColor - (default null) the background stroke color
backgroundBorderWidth - (default null) thickness of the background border
corner - (default 0) the round of corner of the background if there is one
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
backgroundDashed - (default null) set to true for dashed background border (if backgroundBorderColor or backgroundBorderWidth set)
padding - (default 10 if backgroundColor set) places the border this amount from text (see paddingHorizontal and paddingVertical)
padding parameters are ignored if there is no backgroundColor set (also ignored if a backing parameter is set)
paddingHorizontal - (default padding) places border out at top bottom
paddingVertical - (default padding) places border out at left and right
shiftHorizontal - (default 0) move the label (CreateJS Text) inside the Label container horizontally
shiftVertical - (default 0) move the label (CreateJS Text) inside the Label container vertically
rollPersist - (default false) set to true to maintain rollover stage as long as mousedown or press is activated (used by Buttons)
labelWidth - (default null) the same as the lineWidth - the text will wrap at the labelWidth (added to match labelHeight)
labelHeight - (default null) the height of the text - setting this will probably alter the font size - so the size parameter is overwritten
for labelHeight to work, the labelWidth must also be set
using labelWidth and labelHeight together allow you to fit as much text into specified width and height dimensions
maxSize - (default null) set to limit the font size when using labelWidth and labelHeight
bold - (default false) set to true to bold the tip
italic - (default false) set to true to italic the tip
variant - (default false) set to true to set the tip to small caps
splitWords - (default false) set to true to split words when wrapping
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show(delay, time) - show the tip - delay in s defaults to 0 and time in s defaults to 2 (also see ZIM TIME constant)
hide() - hides tip - show() will also hide the tip automatically after the time provided
clear() - hides tip and removes the call to a delayed tip using a delay time in show()
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: see all methods of a Label() such as setColorRange(), etc.
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
align - get or set the horizontal alignment
valign - get or set the vertical alignment
text - get or set the text of the Tip
ALSO: see all properties of a Label() such as size, color, etc.
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+57.6
zim.Tip = function(text, align, valign, margin, marginH, marginV, outside, target, size, font, color, rollColor, shadowColor, shadowBlur, textAlign, textValign, lineWidth, lineHeight, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, bold, italic, variant, splitWords, style, group, inherit) {
var sig = "text, align, valign, margin, marginH, marginV, outside, target, size, font, color, rollColor, shadowColor, shadowBlur, textAlign, textValign, lineWidth, lineHeight, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, bold, italic, variant, splitWords, style, group, inherit";
var duo; if (duo = zob(zim.Tip, arguments, sig, this)) return duo;
z_d("57.6");
this.group = group;
var DS = style===false?{}:zim.getStyle("Tip", this.group, inherit);
if (zot(text)) text = DS.text!=null?DS.text:"Here's a tip!";
if (zot(margin)) margin = DS.margin!=null?DS.margin:40;
if (zot(marginH)) marginH = DS.marginH!=null?DS.marginH:margin;
if (zot(marginV)) marginV = DS.marginV!=null?DS.marginV:margin;
if (zot(align)) align = DS.align!=null?DS.align:"right";
if (zot(valign)) valign = DS.valign!=null?DS.valign:"bottom";
if (zot(outside)) outside = DS.outside!=null?DS.outside:false;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:zim.blue;
if (zot(color)) color = DS.color!=null?DS.color:zim.white;
if (zot(corner)) corner = DS.corner!=null?DS.corner:25;
if (zot(corner)) corner = DS.corner!=null?DS.corner:25;
if (zot(corner)) corner = DS.corner!=null?DS.corner:25;
if (zot(paddingHorizontal)) paddingHorizontal = DS.paddingHorizontal!=null?DS.paddingHorizontal:14+(Array.isArray(corner)?corner[0]:corner);
if (zot(shadowColor) || shadowColor=="ignore") shadowColor=(DS.shadowColor!=null&&shadowColor!="ignore")?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur) || shadowBlur=="ignore") shadowBlur=(DS.shadowBlur!=null&&shadowBlur!="ignore")?DS.shadowBlur:1;
this.zimLabel_constructor(text, size, font, color, rollColor, null, null, textAlign, textValign, bold, italic, variant, lineWidth, lineHeight, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, splitWords, style, group, zim.copy(DS));
this.type = "Tip";
if (outside) {
marginH = -marginH;
marginV = -marginV;
}
var that = this;
that.align = align;
that.valign = valign;
this.background.sha(shadowColor, 3, 5, shadowBlur);
this.show = function(delay, time) {
var timeType = getTIME(time);
if (zot(delay)) delay = DS.delay!=null?DS.delay:0;
if (zot(time)) time = DS.time!=null?DS.time:timeType=="s"?2:2000;
var mess = "zim Tip(): Please pass in a reference to a container with bounds set as parameter to Tip";
if (zot(target)) {
if (zdf) {
target = zdf.stage;
} else {
return that;
}
} else if (!target.getBounds) {
return that;
} else if (zot(target.stage)) {
zog("zim display - Waiter(): The container must have a stage property");
return that;
}
if (delay > 0) {
that.showID = zim.timeout(delay, doShow);
} else {
doShow();
}
function doShow() {
if (target.boundsToGlobal) var b = target.boundsToGlobal();
else var b = target.getBounds();
var container = new zim.Container(b.x, b.y, b.width, b.height);
container.zimTemp = true;
container.loc(0, 0, target.stage);
if (that.align=="center" || that.align=="middle" || that.valign=="center" || that.valign=="middle") {
that.center(container);
}
that.pos((that.align == "center" || that.align == "middle") ? null : marginH, (that.valign == "center" || that.valign == "middle") ? null : marginV, (that.align == "right"), (that.valign == "bottom"), container);
if (outside) {
if (that.align == "right") that.x += that.width;
else if (that.align == "left") that.x -= that.width;
if (that.valign == "bottom") that.y += that.height;
else if (that.valign == "top") that.y -= that.height;
}
that.addTo(container.stage); // will transfer over position...
if (container.zimTemp && container.removeFrom) { container.removeFrom(); container = null; }
container = that.stage;
if (that.timeoutID) that.timeoutID.clear();
that.timeoutID = zim.timeout(time, function () {
that.hide();
container.stage.update();
});
// setTimeout(function() {
if (that.upID) container.stage.off("stagemouseup", that.upID);
that.upID = container.stage.on("stagemouseup", function () {
that.hide();
if (container.stage) container.stage.update();
});
// }, 200);
if (container.stage) container.stage.update();
}
return that;
};
this.hide = function() {
this.removeFrom();
if (this.timeoutID) this.timeoutID.clear();
if (this.upID && target.stage) target.stage.off("stagemouseup", this.downID);
return that;
};
this.clear = function() {
if (that.showID) that.showID.clear();
that.hide();
};
if (style !== false) zim.styleTransforms(this, DS);
this.clone = function () {
return that.cloneProps(new zim.Tip(text, align, valign, margin, marginH, marginV, outside, target, size, font, color, rollColor, shadowColor, shadowBlur, textAlign, textValign, lineWidth, lineHeight, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, splitWords, style, this.group, inherit));
};
};
zim.extend(zim.Tip, zim.Label, "clone", "zimLabel", false);
//-57.6
/*--
zim.Pane = function(width, height, label, backgroundColor, color, draggable, resets, modal, corner, backdropColor, shadowColor, shadowBlur, center, displayClose, backdropClose, backing, fadeTime, container, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, close, closeColor, style, group, inherit)
Pane
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Adds a window for alerts, etc.
You need to call the pane.show() to show the pane and pane.hide() to hide it.
You do not need to add it to the stage - it adds itself centered.
You can change the x and y (the origin and registration point are in the middle).
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var pane = new Pane(300, 200, "Watch out!", "#CCC");
pane.show(); // pressing anywhere will close pane (see parameters for options)
END EXAMPLE
EXAMPLE
var pane = new Pane({width:600, height:250, modal:false, displayClose:false});
var cancel = new Button(220, 100, "CANCEL", "red").center(pane).mov(-130);
var confirm = new Button(220, 100, "CONFIRM", "green").center(pane).mov(130);
cancel.on("click", function() {pane.hide();});
confirm.on("click", function() {zgo("http://zimjs.com")});
pane.show(); // pressing anywhere will close pane (see parameters for options)
// custom backing with ZIM Pizzazz 3
// up top link to https://d309knd7es5f10.cloudfront.net/pizzazz_03.js
new Pane({
label:new Label({color:white, text:"STOP", size:50}),
backing:pizzazz.makePattern({
type:"stripes",
colors:series(red,black),
rows:20
}).alp(.8)
}).show();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 200) width of pane
height - (default 200) height of pane
label - (default null) an optional ZIM Label (or text for default label properties)
backgroundColor - (default "white") a css color for the background of the Pane
color - (default "black") a css color for the text color of the Pane
draggable - (default false) pass in true to drag the pane
resets - (default true) resets position to start on re-open - set to false to keep last position
modal - (default true) pane will close when user clicks off the pane - set to false to keep pane open
corner - (default 20) is the corner radius - set to 0 for no corner
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
backdropColor - (default "rgba(0,0,0,.2)") the color of the background that fills the stage
shadowColor - (default "rgba(0,0,0,.3)") set to -1 for no shadow
shadowBlur - (default 20) how blurred the shadow is if shadow is set
center - (default true) centers the pane
if center is false you will have to set x and y for the pane
the registration point and the origin inside the pane is in the center
you can adjust the label placement by changing its x and y or registration point
displayClose - (default true) closes the Pane if display backing is pressed
if draggable is set to true, displayClose will automatically be set to false
backdropClose - (default true) closes the Pane if backdrop is pressed
backing - (default null) a Display object for the backing of the pane (eg. Shape, Bitmap, Container, Sprite)
see ZIM Pizzazz module for a fun set of Shapes like Boomerangs, Ovals, Lightning Bolts, etc.
as well as patterned backings using Pizzazz 3
fadeTime - (default 0) seconds to fade in and out - also see ZIM TIME constant
container - (default - the default stage) container for the pane
titleBar - (default null - no titleBar) a String or ZIM Label title for the pane that will be presented on a titleBar across the top
titleBarColor - (default "black") the color of the titleBar text if a titleBar is requested
titleBarBackgroundColor - (default "rgba(0,0,0,.2)") the background color of the titleBar if a titleBar is requested
titleBarHeight - (default fit label) the height of the titleBar if a titleBar is requested
close - (default false) - a close X for the top right corner that closes the pane when pressed
closeColor - (default #555) - the color of the close X if close is requested
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show() - shows the pane (returns the pane for chaining)
hide(callEvent) - hides the pane - callEvent defaults to false - set to true to also call close event
toggle(state - default null) - shows if hidden and hides if showing (returns the pane for chaining)
or pass in true to show pane or false to hide pane
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied (returns the new pane for chaining)
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
backing - or display - reference to the pane box
text - gives access to the label text
label - gives access to the label
titleBar - gives access to the titleBar Container - which also has a background property
titleBarLabel - gives access to the titleBar label
toggled - read-only Boolean property as to whether pane is showing
close - access to the ZIM Shape if there is a close X
backdrop - reference to the backdrop that covers the stage
container - get or set the container the pane will be added to
resetX - if reset is true you can dynamically adjust the position if needed
resetY - and the y position for reset...
enabled - set to false to disable component
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "close" event when closed by clicking on backing, display, close, etc. when applicable
dispatches a "fadedin" event if fadeTime is set and pane has finished its fade in animation
dispatches a "fadedout" event if fadeTime is set and pane has finished its fade out animation
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+58
zim.Pane = function(width, height, label, backgroundColor, color, draggable, resets, modal, corner, backdropColor, shadowColor, shadowBlur, center, displayClose, backdropClose, backing, fadeTime, container, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, close, closeColor, style, group, inherit) {
var sig = "width, height, label, backgroundColor, color, draggable, resets, modal, corner, backdropColor, shadowColor, shadowBlur, center, displayClose, backdropClose, backing, fadeTime, container, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, close, closeColor, style, group, inherit";
var duo; if (duo = zob(zim.Pane, arguments, sig, this)) return duo;
z_d("58");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Pane";
var mess = "zim display - Pane(): Please pass in a reference to a container with bounds set as first parameter";
if (zot(container)) {
if (zdf) {
container = zdf.stage;
} else {
zog(mess);
return;
}
} else if (!container.getBounds) {
zog(mess);
return;
} else if (zot(container.getStage)) {
zog("zim display - Pane(): The container must have a stage property");
return;
}
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(width)) width=DS.width!=null?DS.width:200;
if (zot(height)) height=DS.height!=null?DS.height:200;
if (zot(label)) label = DS.label!=null?DS.label:null;
if (typeof label === "string" || typeof label === "number") label = new zim.Label({
text:label, size:DS.size!=null?DS.size:40, align:DS.align!=null?DS.align:"center", valign:DS.valign!=null?DS.valign:"center", color:DS.color!=null?DS.color:color,
backing:"ignore", shadowColor:"ignore", shadowBlur:"ignore", padding:"ignore", backgroundColor:"ignore",
group:this.group
});
if (zot(backgroundColor)) backgroundColor=DS.backgroundColor!=null?DS.backgroundColor:"white";
if (zot(draggable)) draggable=DS.draggable!=null?DS.draggable:false;
if (zot(resets)) resets=DS.resets!=null?DS.resets:true;
if (zot(modal)) modal=DS.modal!=null?DS.modal:true;
if (zot(corner)) corner=DS.corner!=null?DS.corner:20;
if (zot(titleBar)) titleBar = DS.titleBar!=null?DS.titleBar:null;
if (zot(titleBarColor)) titleBarColor = DS.titleBarColor!=null?DS.titleBarColor:null;
if (zot(titleBarBackgroundColor)) titleBarBackgroundColor = DS.titleBarBackgroundColor!=null?DS.titleBarBackgroundColor:null;
if (zot(titleBarHeight)) titleBarHeight = DS.titleBarHeight!=null?DS.titleBarHeight:null;
if (zot(backdropColor)) backdropColor=DS.backdropColor!=null?DS.backdropColor:"rgba(0,0,0,.2)";
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:20;
if (zot(center)) center=DS.center!=null?DS.center:true;
if (zot(displayClose)) displayClose=DS.displayClose!=null?DS.displayClose:true;
if (draggable) displayClose = false;
if (zot(backdropClose)) backdropClose=DS.backdropClose!=null?DS.backdropClose:true;
if (zot(fadeTime)) fadeTime=DS.fadeTime!=null?DS.fadeTime:0;
if (zot(close)) close=DS.close!=null?DS.close:false;
if (zot(closeColor)) closeColor=DS.closeColor!=null?DS.closeColor:"#555";
var backdrop = this.backdrop = new zim.Shape({style:false});
backdrop.type = "CreateJS_Shape";
// make a big backing that closes the pane when clicked
// could also provide a close button
var g = backdrop.graphics;
g.f(backdropColor);
g.drawRect(-5000,-5000,10000,10000);
// makes it seem like the pane has the dimensions of the display
this.setBounds(-width/2,-height/2, width, height);
var that = this;
that.container = container;
backdrop.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", backdropClose?closePane:function(e){e.stopImmediatePropagation();});
var htmlList = new zim.Dictionary(true);
function closePane(e) {
removePane();
that.container.stage.update();
that.dispatchEvent("close");
e.stopImmediatePropagation();
}
backdrop.on("mousedown", function(e) {
e.stopImmediatePropagation();
});
if (modal) this.addChild(backdrop);
var display;
if (zot(backing)) {
display = this.backing = this.display = new zim.Rectangle({
width:width, height:height, color:backgroundColor, corner:corner, style:false
});
} else {
if (backing.type == "Pattern") {
var pattern = backing;
// width, height, color, borderColor, borderWidth, corner, dashed, strokeObj, style, group, inherit
display = new zim.Rectangle(width, height, backgroundColor, null, null, corner, null, null, false);
pattern.centerReg(display);
pattern.setMask(display.shape);
} else {
display = backing;
}
that.display = that.backing = display;
}
if (displayClose) {
display.cursor = "pointer";
display.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", closePane);
}
if (shadowColor != -1 && shadowBlur > 0) display.shadow = new createjs.Shadow(shadowColor, 8, 8, shadowBlur);
display.on("click", function(e) {
// stops the click from going through the display to the background
e.stopImmediatePropagation();
});
this.resetX; this.resetY;
if (draggable) {
display.cursor = "pointer";
var diffX, diffY;
var stage;
display.on("mousedown", function(e) {
stage = e.target.stage;
if (isNaN(that.resetX)) that.resetX = that.x;
if (isNaN(that.resetY)) that.resetY = that.y;
diffX = e.stageX/zim.scaX - that.x;
diffY = e.stageY/zim.scaY - that.y;
display.cursor = "pointer";
});
display.on("pressmove", function(e) {
var p = checkBounds(e.stageX/zim.scaX-diffX, e.stageY/zim.scaY-diffY);
that.x = p.x;
that.y = p.y;
var ch;
for (var i=0; i 0) {
that.animate({obj:{alpha:0}, time:fadeTime, call:function(){
end();
that.dispatchEvent("fadedout");
}});
} else {
end();
}
function end() {
that.container.removeChild(that);
var ch;
for (var i=0; i=0; i--) { // remove textareas and loaders second
ch = that.getChildAt(i);
if (ch.type == "TextArea" || ch.type == "Loader" || ch.type == "Tag") {
that.removeChild(ch);
}
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE))) that.container.stage.update();
if (resets) {
if (!isNaN(that.resetX)) that.x = that.resetX;
if (!isNaN(that.resetY)) that.y = that.resetY;
}
if (that.zimAccessibility) {
var a = that.zimAccessibility;
a.resize(that);
if (accessibilityClicker) accessibilityClicker.focus();
else that.zimTabTag.nextSibling.focus();
setTimeout(function() {a.talk("Pane has been closed.");}, 50);
}
}
}
var accessibilityClicker;
this.show = function() {
if (center) {
if (isNaN(that.resetX)) {
that.x = (that.container.getBounds().width) /2;
that.y = (that.container.getBounds().height) /2;
}
}
that.container.addChild(that);
for (var i=0; i 0) {
that.alpha = 0;
that.animate({
props:{alpha:1},
time:fadeTime,
call:function(){
that.dispatchEvent("fadedin");
}
});
} else {
if (that.container.stage) that.container.stage.update();
}
if (that.zimAccessibility) {
var a = that.zimAccessibility;
setTimeout(function(){if (a.activatedObject) accessibilityClicker = a.activatedObject.zimTabTag;}, 50);
a.resize(that);
a.tabIndex = that.zimTabIndex;
}
that.toggled = true;
return that;
};
function checkBounds(x,y) {
x = Math.max(width/2, Math.min(that.container.getBounds().width-width/2, x));
y = Math.max(height/2, Math.min(that.container.getBounds().height-height/2, y));
return {x:x,y:y};
}
this.toggle = function(state) {
if (state===true) that.show();
else if (state===false) that.hide();
else if (that.container.contains(that)) that.hide();
else that.show();
return that;
};
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
var lX = label.x; // new Panes automatically center the label
var lY = label.y;
var p2 = that.cloneProps(new zim.Pane(width, height, label.clone(), backgroundColor, color, draggable, resets, modal, corner, backdropColor, shadowColor, shadowBlur, center, displayClose, backdropClose, zot(backing)?backing.clone():null, fadeTime, that.container, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, close, closeColor, style, this.group, inherit));
p2.label.x = lX;
p2.label.y = lY;
return p2;
};
};
zim.extend(zim.Pane, zim.Container, "clone", "zimContainer", false);
//-58
/*--
zim.Panel = function(width, height, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, backgroundColor, borderColor, borderWidth, corner, close, closeColor, arrow, align, shadowColor, shadowBlur, draggable, boundary, extraButton, collapse, collapsed, style, group, inherit)
Panel
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A simple panel with titleBar and optional arrow for more panels.
Panel can be set draggable and can have a close button
See: https://zimjs.com/explore/panel.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var panel = new Panel({titleBar:series("TODAY", "TOMORROW")})
.center();
// make a couple pages for the panels
// content for panel 1
var today = new Container(panel.width, panel.height).addTo(panel);
var sun = new Circle(30, yellow).center(today);
// content for panel 2
var tomorrow = new Container(panel.width, panel.height); // do not add yet
var label = new Label("-30").center(tomorrow);
// event to change content as panels change
panel.on("change", function () {
if (today.parent) {
today.removeFrom();
tomorrow.center(panel);
} else {
tomorrow.removeFrom();
today.center(panel);
}
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 250) the width of the panel
height - (default 300) the height of the panel
titleBar - |ZIM VEE| (default "PANEL") a String or ZIM Label title for the panel that will be presented on a titleBar across the top
titleBarColor - |ZIM VEE| (default "black") the text color of the titleBar if a titleBar is requested
titleBarBackgroundColor - |ZIM VEE| (default "rgba(0,0,0,.2)") the background color of the titleBar if a titleBar is requested
titleBarHeight - (default fit label) the height of the titleBar if a titleBar is requested
backgroundColor - |ZIM VEE| (default #eee) background color (use clear - or "rbga(0,0,0,0)" for no background)
borderColor - |ZIM VEE| (default #888) border color
borderWidth - (default 1) the thickness of the border
corner - (default 0) the round of corner
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
close - (default false) - add a close button top right
closeColor - (default titleBarColor) the color of the close button
arrow - (default true if more than one panel) set to false to not show an arrow if multiple panels
align - (default "left") set to "center", "middle" or "right" to align the label on the titleBar
shadowColor - (default "rgba(0,0,0,.3)" if shadowBlur) the shadow color - set to -1 for no shadow
shadowBlur - (default 14 if shadowColor) the shadow blur - set to -1 for no shadow
draggable - (default true if titleBar) set to false to not allow dragging titleBar to drag window
boundary - (default null) set to ZIM Boundary() object - or CreateJS.rectangle()
extraButton - (default null) creates a little square button with the letter R for reset
this is made with the group style id of "extraButton"
use the extraButton property to access the button to change its label or capture an event, etc.
collapse - (default false) set to true to double click panel title bar to collapse and unCollapse panel
collapsed - (default false) set to true to start the panel collapsed
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
nextPanel(index, event) - show next panel - the panels are set up to be a series or random or function based
this means there is not necessarily an order to be able to go backwards to... so, only forward!
If a series is provided to the Panel title, etc. then the index can be used to go to the title in the series at the index
event (default false) will dispatch a change event if nextPanel is called
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
panelHeight - get and set the height of the panel without scaling it as height does (for width, remake the Panel object)
titleBar - access to the titleBar container
label - access to the label of the current panel
text - access to the text of the current panel
titleBar - gives access to the titleBar Container - which also has a background property
titleBarLabel - gives access to the titleBar label
close - access to the close button
collapsed - pass in true to collapse the panel and false to unCollapse the panel
arrow - access to the next arrow
background - access to the background Rectangle
extraButton - access to the Label for the extra button if extraButton parameter is set to true
use this to set the text in the button (a one letter button is expected - for instance, i for info, x for close, etc.)
overlay - access to the overlay Rectangle used if enabled = false
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event when arrow is pressed to go to the next panel
dispatches a "close" event when closed with close button if there is a close button
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+57.7
zim.Panel = function(width, height, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, backgroundColor, borderColor, borderWidth, corner, close, closeColor, arrow, align, shadowColor, shadowBlur, draggable, boundary, extraButton, collapse, collapsed, style, group, inherit) {
var sig = "width, height, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, backgroundColor, borderColor, borderWidth, corner, close, closeColor, arrow, align, shadowColor, shadowBlur, draggable, boundary, extraButton, collapse, collapsed, style, group, inherit";
var duo; if (duo = zob(zim.Panel, arguments, sig, this)) return duo;
z_d("57.7");
this.group = group;
var DS = style===false?{}:zim.getStyle("Panel", this.group, inherit);
if (zot(width)) width=DS.width!=null?DS.width:250;
if (zot(height)) height=DS.height!=null?DS.height:300;
this.zimContainer_constructor(width, height, null, null, false);
this.type = "Panel";
if (zot(titleBar)) titleBar = DS.titleBar!=null?DS.titleBar:"PANEL";
if (zot(titleBarColor)) titleBarColor = DS.titleBarColor!=null?DS.titleBarColor:"#fff";
if (zot(titleBarBackgroundColor)) titleBarBackgroundColor = DS.titleBarBackgroundColor!=null?DS.titleBarBackgroundColor:"#555";
if (zot(titleBarHeight)) titleBarHeight = DS.titleBarHeight!=null?DS.titleBarHeight:30;
if (zot(backgroundColor)) backgroundColor=DS.backgroundColor!=null?DS.backgroundColor:"#eee";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"#888";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(corner)) corner=DS.corner!=null?DS.corner:5;
if (zot(align)) align=DS.align!=null?DS.align:"left";
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:14;
if (zot(draggable)) draggable = DS.draggable!=null?DS.draggable:false;
if (zot(boundary)) boundary = DS.boundary!=null?DS.boundary:null;
if (zot(close)) close=DS.close!=null?DS.close:false;
if (zot(closeColor)) closeColor = DS.closeColor != null ? DS.closeColor : !zot(titleBarColor) ? titleBarColor : "#555";
if (zot(arrow)) arrow=DS.arrow!=null?DS.arrow:zim.vee(titleBar);
if (!Array.isArray(corner)) corner = [corner,corner,corner,corner];
if (zot(collapse)) collapse=DS.collapse!=null?DS.collapse:false;
if (zot(collapsed)) collapsed=DS.collapsed!=null?DS.collapsed:false;
var that = this;
var background = this.background = new zim.Rectangle(width, height, backgroundColor, borderColor, borderWidth, corner).addTo(this);
if (shadowColor != -1 && shadowBlur > 0) {
this.background.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
var titleBarValue = titleBar; // as we assign the container to titleBar later
var t = zim.Pick.choose(titleBarValue);
var tBarColor = zim.Pick.choose(titleBarColor);
var tBarBackgroundColor = zim.Pick.choose(titleBarBackgroundColor);
var pBackgroundColor = zim.Pick.choose(backgroundColor);
var pBorderColor = zim.Pick.choose(borderColor);
if (typeof t == "string") t = new zim.Label({
text:t, color:tBarColor, size:DS.size!=null?DS.size:20, bold:DS.bold!=null?DS.bold:false,
backing:"ignore", shadowColor:"ignore", shadowBlur:"ignore", padding:"ignore", backgroundColor:"ignore",
group:this.group
});
var titleBarLabel = that.titleBarLabel = t;
if (zot(tBarBackgroundColor)) tBarBackgroundColor = "rgba(0,0,0,.2)";
that.titleBar = titleBar = new zim.Container(width, titleBarHeight, null, null, false).loc(0,0,that);
var titleBarRect = that.titleBar.backing = new zim.Rectangle(width+borderWidth, titleBarHeight, tBarBackgroundColor, null, null, [corner[0]*.95, corner[1]*.95, 0, 0], true, null, false).center(titleBar);
if (titleBar) positionBar();
that.label = t;
that.text = t.text;
if (close) {
var close = that.close = new zim.Shape(-40,-40,80,80,null,false);
close.graphics.f(closeColor).p("AmJEVIEUkTIkXkWIB4h5IEWEYIETkTIB4B3IkTESIEQERIh4B4IkRkRIkSEVg"); // width about 90 reg in middle
if (titleBar) {
close.centerReg(titleBar)
.scaleTo(titleBar, null, 50);
if (align=="right") close.pos(Math.max(corner[1]/2, 15));
else close.pos(Math.max(corner[1]/2, 15), null, true);
} else {
close.addTo(that)
.sca(.3)
.mov(width/2-close.width-3, -height/2+close.height);
}
close.expand(40);
close.cursor = "pointer";
close.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", function () {
var s = that.stage;
that.removeFrom();
that.dispatchEvent("close");
s.update();
});
}
if (collapse) {
if (collapsed) that.collapsed = true;
that.collapseEvent = that.titleBar.on("dblclick", function () {
collapsed = !collapsed;
that.collapsed = collapsed;
});
}
this.nextPanel = function(index, event) {
var t = zot(index)||zot(titleBarValue.array)?zim.Pick.choose(titleBarValue):titleBarValue.array[index];
var tBarColor = zot(index)||zot(titleBarColor.array)?zim.Pick.choose(titleBarColor):titleBarColor.array[index];
var tBarBackgroundColor = zot(index)||zot(titleBarBackgroundColor.array)?zim.Pick.choose(titleBarBackgroundColor):titleBarBackgroundColor.array[index];
var pBackgroundColor = zot(index)||zot(backgroundColor.array)?zim.Pick.choose(backgroundColor):backgroundColor.array[index];
var pBorderColor = zot(index)||zot(borderColor.array)?zim.Pick.choose(borderColor):borderColor.array[index];
if (typeof t == "string") t = new zim.Label({
text:t, color:tBarColor, size:DS.size!=null?DS.size:20,
backing:"ignore", shadowColor:"ignore", shadowBlur:"ignore", padding:"ignore", backgroundColor:"ignore",
group:this.group
});
that.label = t;
that.text = t.text;
titleBarLabel.removeFrom();
titleBarLabel = that.titleBarLabel = t;
positionBar();
titleBarRect.color = tBarBackgroundColor;
that.background.color = pBackgroundColor;
that.background.borderColor = pBorderColor;
if (event) that.dispatchEvent("change");
if (!OPTIMIZE && that.stage) that.stage.update();
};
function positionBar() {
if (align=="right") titleBarLabel.center(titleBar).pos(Math.max(corner[0]/2, 10), null, true);
else if (align=="center" || align=="middle") titleBarLabel.center(titleBar);
else titleBarLabel.center(titleBar).loc(Math.max(corner[0]/2, 10));
titleBarLabel.mov(0,2);
}
if (draggable) {
titleBar.cursor = "pointer";
titleBar.on("mousedown", function() {
that.drag({rect:boundary, currentTarget:true});
});
titleBar.on("pressup", function() {
that.noDrag(false); // false for not recursive - leave objects inside so they do not lose their own cursors
});
}
if (arrow > 0) {
var added = close?close.width+15:0;
var next = that.arrow = new zim.Shape(-20,-20,40,40,null,false);
next.graphics.f(titleBarColor).p("AiJieIETCeIkTCfg"); // width about 90 reg in middle
next.centerReg(titleBar).scaleTo(titleBar, null, 70).alp(.8).hov(1).expand();
if (align=="right") next.pos(Math.max(corner[1]/2, 10)+added);
else next.pos(Math.max(corner[1]/2, 10)+added, null, true);
next.cursor = "pointer";
next.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", function(){
that.nextPanel();
that.dispatchEvent("change");
});
}
if (!zot(extraButton)) {
var extraButton = that.extraButton = new zim.Button({
label:"R",
width:50,
height:50,
corner:5,
group:"PanelExtra"
}).scaleTo(titleBar, null, 70).centerReg(titleBar).expand();
if (align=="left") {
extraButton.pos(arrow>0?next.x-next.width-25:Math.max(corner[1]/2, 10) );
} else {
extraButton.pos((arrow>0&&align!="center")?next.x+next.width: Math.max(corner[1]/2, 10));
}
}
var overlay = that.overlay = new zim.Rectangle(width, height, null, null, null, corner).alp(.3);
Object.defineProperty(that, 'panelHeight', {
get: function() {
return that.background.height;
},
set: function(value) {
background.removeFrom();
background = this.background = new zim.Rectangle(width, value, backgroundColor, borderColor, borderWidth, corner)
.addTo(this).bot();
if (shadowColor != -1 && shadowBlur > 0) {
this.background.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
that.setBounds(width, value);
if (!OPTIMIZE && that.stage) that.stage.update();
}
});
Object.defineProperty(that, 'collapsed', {
get: function() {
return collapsed;
},
set: function(value) {
collapsed = value;
if (collapsed) that.setMask(that.titleBar.backing, true);
else that.setMask(null);
if (that.stage) that.stage.update();
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
if (!value) that.overlay.addTo(that);
else that.overlay.removeFrom();
if (!OPTIMIZE && that.stage) that.stage.update();
}
});
if (style !== false) zim.styleTransforms(this, DS);
this.clone = function () {
return that.cloneProps(new zim.Toggle(width, height, titleBar ? titleBar.clone() : "", titleBarColor, titleBarBackgroundColor, titleBarHeight, backgroundColor, borderColor, borderWidth, corner, close, closeColor, arrow, align, shadowColor, shadowBlur, draggable, boundary, extraButton, collapse, collapsed, style, this.group, inherit));
};
this.doDispose = function(a,b,disposing) {
// need to dispose properly for Panel
if (collapse) this.titleBar.off("dblclick", this.collapseEvent);
if (!disposing) this.zimContainer_dispose(true);
return true;
}
};
zim.extend(zim.Panel, zim.Container, ["clone", "dispose"], "zimContainer", false);
zim.Panel.prototype.dispose = function(disposing) {return this.doDispose(null,null,disposing);};
//-57.7
/*--
zim.Window = function(width, height, backgroundColor, borderColor, borderWidth, padding, corner, swipe, scrollBarActive, scrollBarDrag, scrollBarColor, scrollBarAlpha, scrollBarFade, scrollBarH, scrollBarV, slide, slideDamp, slideSnap, interactive, shadowColor, shadowBlur, paddingHorizontal, paddingVertical, scrollWheel, damp, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, draggable, boundary, onTop, close, closeColor, cancelCurrentDrag, fullSize, fullSizeColor, resizeHandle, style, group, inherit)
Window
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Adds a window for content that can be swiped and scrolled.
NOTE: if zim namespace zns = true then this overwrites a JS Window - so the JS Window is stored as document.window
NOTE: set the enable property to false if animating the position of the whole Window
then set the enable property to true on the animate call function. See update() method for more.
NOTE: to add ZIM Swipe() to objects in window set the overrideNoSwipe parameter of Swipe to true
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var win = new Window({
height:300,
interactive:false,
padding:0,
slideDamp:.2
});
var container = new Container(); // make some content
var c; spacing = 10;
for (var i=0; i<4; i++) {
c = frame.makeCircles();
c.x = win.width/2;
c.y = c.width/2 + (c.width+spacing)*i;
container.addChild(c);
}
win.add(container); // add the content to the window
win.center();
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 300) the width of the window
height - (default 200) the height of window - including the titleBar if there is a titleBar
backgroundColor - (default #333) background color (use clear - or "rbga(0,0,0,0)" for no background)
borderColor - (default #999) border color
borderWidth - (default 1) the thickness of the border
padding - (default 0) places the content in from edges of border (see paddingHorizontal and paddingVertical)
padding is ignored if content x and y not 0 - and really only works on top left - so more like an indent
corner - (default 0) is the rounded corner of the window (does not accept corner array - scrollBars are too complicated)
swipe - (default auto/true) the direction for swiping set to none / false for no swiping
also can set swipe to just vertical or horizontal
scrollBarActive - (default true) shows scrollBar (set to false to not)
scrollBarDrag - (default false) set to true to be able to drag the scrollBar
scrollBarColor - (default borderColor) the color of the scrollBar
scrollBarAlpha - (default .3) the transparency of the scrollBar
scrollBarFade - (default true) fades scrollBar unless being used
scrollBarH - (default true) if scrolling in horizontal is needed then show scrollBar
scrollBarV - (default true) if scrolling in vertical is needed then show scrollBar
slide - (default true) Boolean to throw the content when drag/swipe released
slideDamp - (default .6) amount the slide damps when let go 1 for instant, .01 for long slide, etc.
slideSnap - (default "vertical") "auto" / true, "none" / false, "horizontal"
slides past bounds and then snaps back to bounds when released
vertical snaps when dragging up and down but not if dragging horizontal
interactive - (default true) allows interaction with content in window
set to false and whole window will be swipeable but not interactive inside
shadowColor - (default rgba(0,0,0,.3)) the color of the shadow
shadowBlur - (default 20) set shadowBlur to -1 for no drop shadow
paddingHorizontal - (default padding) places content in from left and right (ignored if content x not 0)
paddingVertical - (default padding) places content in from top and bottom (ignored if content y not 0)
scrollWheel - (default true) scroll vertically with scrollWheel
damp - (default null) set to .1 for instance to damp the scrolling
titleBar - (default null - no titleBar) a String or ZIM Label title for the window that will be presented on a titleBar across the top
titleBarColor - (default "black") the text color of the titleBar if a titleBar is requested
titleBarBackgroundColor - (default "rgba(0,0,0,.2)") the background color of the titleBar if a titleBar is requested
titleBarHeight - (default fit label) the height of the titleBar if a titleBar is requested
draggable - (default true if titleBar) set to false to not allow dragging titleBar to drag window
boundary - (default null) set to ZIM Boundary() object - or CreateJS.rectangle()
onTop - (default true) set to false to not bring Window to top of container when dragging
close - (default false) - a close X for the top right corner that closes the window when pressed
closeColor - (default #555) - the color of the close X if close is requested
cancelCurrentDrag - (default false) - set to true to cancel window dragging when document window loses focus
this functionality seems to work except if ZIM is being used with Animate - so we have left it turned off by default
fullSize - (default false) - set to true to add a fullsize icon to the titleBar
to let user increase the size of the window to the frame - will turn into a reduce size icon
fullSizeColor - (default #555) - the color of the fullSize icon
resizeHandle - (default false) - set to true to rollover bottom right corner to resize window with resizeHandle
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
add(obj, replace) - adds obj to content container of window (at padding) must have bounds set
it is best to position and size obj first before adding
otherwise if adjusting to outside current content size then call update()
replace defaults to false and if set to true, removes all content then adds the obj.
returns window for chaining
remove(obj) - removes object from content container of window and updates - returns window for chaining
removeAll() - removes all objects from content container of window and updates - returns window for chaining
resize(width, height) - resizes the Window without scaling the content (also calls update() for scroll update)
width and height are optional - returns window for chaining
update() - resets window scrolling if perhaps the content gets bigger or smaller
update() does not quite update the dragBoundary due to a timeout in waiting for scrolls to be set
so if animating the position of a window, set the enable property to false before animating
then set the enable property to true on the animate call function
cancelCurrentDrag() - stop current drag on window - but add dragging back again for next drag
clone(recursive) - makes a copy with properties such as x, y, etc. also copied
recursive (default true) clones the window content as well (set to false to not clone content)
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
backing - CreateJS Shape used for backing of Window
content - ZIM Container used to hold added content
enabled - get or set whether the Window is enabled
scrollEnabled - get or set whether the Window can be scrolled
scrollBar - data object that holds the following properties (with defaults):
you can set after object is made - call window.update() to see change
scrollBar.horizontal = zim Shape // the horizontal scrollBar rectangle shape
scrollBar.vertical = zim Shape // the vertical scrollBar rectangle shape
scrollBar.color = borderColor; // the color of the scrollBar
scrollBar.size = 6; // the width if vertical or the height if horizontal
scrollBar.minSize = 12; // for the height if vertical or the width if horizontal
scrollBar.spacing = 3 + size + borderWidth / 2;
scrollBar.margin = 0; // adds extra space only at end by scrollBars
scrollBar.corner = scrollBar.size / 2;
scrollBar.showTime = .5; // s to fade in
scrollBar.fadeTime = 3; // s to fade out
scrollX - gets and sets the content x position in the window (this will be negative)
scrollY - gets and sets the content y position in the window (this will be negative)
scrollXMax - gets the max we can scroll in x based on content width - window width (plus padding and margin)
scrollYMax - gets the max we can scroll in y based on content height - window height (plus padding and margin)
titleBar - access to the ZIM Container for the titleBar if there is a titleBar also has a backing property
titleBarLabel - access to the ZIM Label of the titleBar if there is a titleBar
close - access to the ZIM Shape if there is a close X
resizeHandle - access the ZIM Rectangle that makes up the resizeHandle when resizeHandle parameter is set to true
resizeHandle.removeFrom() would stop resize from being available and resizeHandle.addTo(window) would activate it again
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "select" event when clicked on in a traditional manner (fast click with little movement)
dispatches a "hoverover" event when rolled on without moving for 300 ms
dispatches a "hoverout" event when not hovering due to movement or mouseout on the window
dispatches a "scrolling" event when the window scrolls
dispatches a "close" event when the window is closed with the x on the titleBar if there is a titleBar
dispatches a "slidestart" event if slide is true and window starts sliding (on pressup)
dispatches a "slidestop" event if slide is true and window stops sliding
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+58.1
zim.Window = function(width, height, backgroundColor, borderColor, borderWidth, padding, corner, swipe, scrollBarActive, scrollBarDrag, scrollBarColor, scrollBarAlpha, scrollBarFade, scrollBarH, scrollBarV, slide, slideDamp, slideSnap, interactive, shadowColor, shadowBlur, paddingHorizontal, paddingVertical, scrollWheel, damp, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, draggable, boundary, onTop, close, closeColor, cancelCurrentDrag, fullSize, fullSizeColor, resizeHandle, style, group, inherit) {
var sig = "width, height, backgroundColor, borderColor, borderWidth, padding, corner, swipe, scrollBarActive, scrollBarDrag, scrollBarColor, scrollBarAlpha, scrollBarFade, scrollBarH, scrollBarV, slide, slideDamp, slideSnap, interactive, shadowColor, shadowBlur, paddingHorizontal, paddingVertical, scrollWheel, damp, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, draggable, boundary, onTop, close, closeColor, cancelCurrentDrag, fullSize, fullSizeColor, resizeHandle, style, group, inherit";
var duo; if (duo = zob(zim.Window, arguments, sig, this)) return duo;
z_d("58.1");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Window";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(width)) width=DS.width!=null?DS.width:300;
if (zot(height)) height=DS.height!=null?DS.height:200;
if (zot(backgroundColor)) backgroundColor=DS.backgroundColor!=null?DS.backgroundColor:"#333";
var originalBorderColor = borderColor;
var originalBorderWidth = borderWidth;
if (zot(borderColor)) borderColor=DS.borderColor!=null?DS.borderColor:"#999";
if (zot(borderWidth)) borderWidth=DS.borderWidth!=null?DS.borderWidth:1; // 0
if (zot(padding)) padding=DS.padding!=null?DS.padding:0;
if (zot(corner)) corner=DS.corner!=null?DS.corner:0;
if (zot(swipe)) swipe=DS.swipe!=null?DS.swipe:true; // true / auto, vertical, horizontal, false / none
if (zot(scrollBarActive)) scrollBarActive=DS.scrollBarActive!=null?DS.scrollBarActive:true;
if (zot(scrollBarDrag)) scrollBarDrag=DS.scrollBarDrag!=null?DS.scrollBarDrag:false;
if (zot(scrollBarColor)) scrollBarColor=DS.scrollBarColor!=null?DS.scrollBarColor:borderColor;
if (zot(scrollBarAlpha)) scrollBarAlpha=DS.scrollBarAlpha!=null?DS.scrollBarAlpha:.3;
if (zot(scrollBarFade)) scrollBarFade=DS.scrollBarFade!=null?DS.scrollBarFade:true;
if (zot(scrollBarH)) scrollBarH = DS.scrollBarH!=null?DS.scrollBarH:true;
if (zot(scrollBarV)) scrollBarV = DS.scrollBarV!=null?DS.scrollBarV:true;
if (scrollBarDrag) scrollBarFade = DS.scrollBarFade!=null?DS.scrollBarFade:false;
if (zot(slide)) slide=DS.slide!=null?DS.slide:true;
if (zot(slideDamp)) slideDamp=DS.slideDamp!=null?DS.slideDamp:.6;
if (zot(slideSnap)) slideSnap=DS.slideSnap!=null?DS.slideSnap:"vertical"; // true / auto, vertical, horizontal, false / none
if (zot(interactive)) interactive=DS.interactive!=null?DS.interactive:true;
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:20;
if (zot(paddingVertical)) paddingVertical=DS.paddingVertical!=null?DS.paddingVertical:padding;
if (zot(paddingHorizontal)) paddingHorizontal=DS.paddingHorizontal!=null?DS.paddingHorizontal:padding;
if (zot(scrollWheel)) scrollWheel = DS.scrollWheel!=null?DS.scrollWheel:true;
if (zot(titleBar)) titleBar = DS.titleBar!=null?DS.titleBar:null;
if (zot(titleBarColor)) titleBarColor = DS.titleBarColor!=null?DS.titleBarColor:null;
if (zot(titleBarBackgroundColor)) titleBarBackgroundColor = DS.titleBarBackgroundColor!=null?DS.titleBarBackgroundColor:null;
if (zot(titleBarHeight)) titleBarHeight = DS.titleBarHeight!=null?DS.titleBarHeight:null;
if (zot(draggable)) draggable = DS.draggable!=null?DS.draggable:null;
if (zot(boundary)) boundary = DS.boundary!=null?DS.boundary:null;
if (zot(onTop)) onTop = DS.onTop!=null?DS.onTop:null;
if (zot(close)) close = DS.close!=null?DS.close:null;
if (zot(closeColor)) closeColor = DS.closeColor!=null?DS.closeColor:null;
if (zot(cancelCurrentDrag)) cancelCurrentDrag = DS.cancelCurrentDrag!=null?DS.cancelCurrentDrag:false;
if (zot(fullSize)) fullSize = DS.fullSize!=null?DS.fullSize:null;
if (zot(fullSizeColor)) fullSizeColor = DS.fullSizeColor!=null?DS.fullSizeColor:null;
if (zot(resizeHandle)) resizeHandle = DS.resizeHandle!=null?DS.resizeHandle:null;
if (titleBar === false) titleBar = null;
if (!zot(titleBar)) {
if (zot(titleBarHeight)) titleBarHeight = 30;
height = height - titleBarHeight;
}
var that = this;
this.scrollX = this.scrollY = this.scrollXMax = this.scrollYMax = 0;
var backing = this.backing = new zim.Shape({style:false});
this.addChild(backing);
var mask = new createjs.Shape();
mask.type = "WindowBacking";
var mg = mask.graphics;
// make the mask in the update function
// when we know if there are vertical and horizontal scrollBars
this.addChild(mask);
var content = this.content = new zim.Container({style:false});
this.addChild(content);
content.mask = mask;
var stage;
if (!interactive) {
// hitArea makes the whole window draggable
// but then you can't interact with the content inside the window
var hitArea = new createjs.Shape();
}
if (borderWidth > 0) {
var border = new createjs.Shape();
this.addChild(border);
}
var titleBarCorner = titleBar?0:corner;
// we call this function at start and when resize() is called to resize the window without scaling content
function sizeWindow() {
that.setBounds(0,0,width,height);
backing.graphics.c().f(backgroundColor).rc(0,0,width,height,titleBarCorner,titleBarCorner,corner,corner);
if (shadowColor != -1 && shadowBlur > 0) backing.shadow = new createjs.Shadow(shadowColor, 4, 4, shadowBlur);
if (borderWidth > 0) {
if (corner) {
border.graphics.c().s(borderColor).ss(borderWidth, "square", "miter").rc(0,0,width,height,titleBarCorner,titleBarCorner,corner,corner);
} else {
border.graphics.c().s(borderColor).ss(borderWidth, "square", "miter").dr(0,0,width,height);
}
}
if (!zot(titleBarRect)) {
titleBarRect = titleBar.backing.widthOnly = that.width;
that.setBounds(0,-titleBarHeight,that.width,height+titleBarHeight);
}
if (that.close) {
if (titleBar) close.pos({x:width-Math.max(corner/2, 10)-close.width/2, y:titleBarHeight/2, reg:true});
else close.pos((Math.max(corner/2, 10))/2, close.height/2, true, false, that);
}
if (that.fullSize) {
fullSize.pos({x:width-Math.max(corner/2, 10)-fullSize.width/2, y:titleBarHeight/2, reg:true});
if (that.close) fullSize.mov(-close.width-10);
}
}
sizeWindow();
// this exposes an scrollBar data object so creators can adjust scrollBar properties
// note that these properties are set dynamically in the update function
var scrollBar = this.scrollBar = {}; // data object to expose scrollBar properties
scrollBar.color = scrollBarColor;
scrollBar.size = 6;
scrollBar.minSize = scrollBar.size*2; // if vertical scroll, this is vertical minSize where size is horizontal size
scrollBar.spacing = 3.5 + borderWidth / 2;
scrollBar.margin = 0;
scrollBar.corner = scrollBar.size / 2;
scrollBar.showTime = .5;
scrollBar.fadeTime = 3;
if (scrollBarActive) {
var hscrollBar = scrollBar.horizontal = new zim.Shape({style:false});
var hg = hscrollBar.graphics;
hscrollBar.alpha = scrollBarAlpha;
this.addChild(hscrollBar);
if (scrollBarDrag) hscrollBar.drag({localBounds: true});
var vscrollBar = scrollBar.vertical = new zim.Shape({style:false});
var vg = vscrollBar.graphics;
vscrollBar.alpha = scrollBarAlpha;
this.addChild(vscrollBar);
if (scrollBarDrag) vscrollBar.drag({localBounds: true});
}
var hProportion;
var vProportion;
var hCheck;
var vCheck;
var gap;
var contentWidth;
var contentHeight;
var hEvent;
var vEvent;
var dTimeout;
this.update = function() {
if (scrollBarActive) {
// clear the scrollBars and remake anytime this function is called
// as these may change as people add and remove content to the Window
hg.clear(); // horizontal scrollBar
vg.clear(); // vertical scrollBar
}
// assume no gap at left and top
// gap is applied in x if there is a scroll in y
// gap is applied in y if there is a scroll in x
gap = (scrollBarActive) ? scrollBar.size+scrollBar.spacing*2 : 0;
contentWidth = content.getBounds()?content.getBounds().width:0;
contentHeight = content.getBounds()?content.getBounds().height:0;
// note, the contentWidth and contentHeight include ONE padding
hCheck = (scrollBarH && contentWidth > width-paddingHorizontal && (scrollBarActive || swipe === true || swipe == "auto" || swipe == "horizontal"));
vCheck = (scrollBarV && contentHeight > height-paddingVertical && (scrollBarActive || swipe === true || swipe == "auto" || swipe == "vertical"));
that.scrollXMax = contentWidth+paddingHorizontal*2-width+(vCheck?gap+scrollBar.margin:0);
that.scrollYMax = contentHeight+paddingVertical*2-height+(hCheck?gap+scrollBar.margin:0);
// set mask dynamically as scrollBars may come and go affecting the mask size slightly
mg.clear();
var xx = borderWidth/2;
var yy = borderWidth/2;
var ww = width-((vCheck && scrollBarActive)?scrollBar.size+scrollBar.spacing*2:0)-(vCheck?0:borderWidth);
var hh = height-((hCheck && scrollBarActive)?scrollBar.size+scrollBar.spacing*2:0)-(hCheck?0:borderWidth);
mg.f("rgba(0,0,0,0)").rc(xx,yy,ww,hh,titleBarCorner,titleBarCorner,vCheck&&scrollBarActive?0:corner,hCheck&&scrollBarActive?0:corner);
mask.setBounds(that.getBounds().x,that.getBounds().y,that.getBounds().width, that.getBounds().height);
zim.expand(mask, 0);
if (!interactive) {
hitArea.graphics.c().f("red").dr(xx,yy,ww,hh);
content.hitArea = hitArea;
}
var edgeAdjust = Math.max(corner, Math.min(scrollBar.corner, scrollBar.spacing));
var edgeLeft = edgeAdjust + borderWidth/2;
var edgeRight = edgeAdjust + (vCheck?gap:0) + borderWidth/2;
var edgeTop = edgeAdjust + borderWidth/2;
var edgeBottom = edgeAdjust + (hCheck?gap:0) + borderWidth/2;
var scrollBarLength;
if (hCheck && scrollBarActive) {
scrollBarLength = Math.max(scrollBar.minSize, (width-edgeLeft-edgeRight) * (width-edgeLeft-edgeRight) / (contentWidth + paddingHorizontal + scrollBar.margin));
hg.f(scrollBar.color).rr(0,0,scrollBarLength,scrollBar.size,scrollBar.corner);
hscrollBar.x = edgeLeft;
hscrollBar.y = height-scrollBar.size-scrollBar.spacing;
// for swiping window:
hProportion = new zim.Proportion(-that.scrollXMax, 0, edgeLeft, width-scrollBarLength-edgeRight, -1);
if (scrollBarDrag) {
hscrollBar.setBounds(0,0,scrollBarLength,scrollBar.size);
// drag rect for scrollBar
var rect = new createjs.Rectangle(
edgeLeft, hscrollBar.y, width-scrollBarLength-edgeLeft-edgeRight, 0
);
hscrollBar.dragBoundary(rect);
hscrollBar.proportion = new zim.Proportion(
rect.x, rect.x+rect.width, 0, -that.scrollXMax
);
hscrollBar.off("pressmove", hEvent);
hEvent = hscrollBar.on("pressmove", function() {
that.dispatchEvent("scrolling");
if (hitArea) {
// move hitarea to display box
hitArea.x = -content.x;
hitArea.y = -content.y;
}
content.x = hscrollBar.proportion.convert(hscrollBar.x);
});
}
}
if (vCheck && scrollBarActive) {
scrollBarLength = Math.max(scrollBar.minSize, (height-edgeTop-edgeBottom) * (height-edgeTop-edgeBottom) / (contentHeight + paddingVertical + scrollBar.margin));
vg.f(scrollBar.color).rr(0,0,scrollBar.size,scrollBarLength,scrollBar.corner);
vscrollBar.x = width-scrollBar.size-scrollBar.spacing;
vscrollBar.y = edgeTop;
// for swiping window:
vProportion = new zim.Proportion(-that.scrollYMax, 0, edgeTop, height-scrollBarLength-edgeBottom, -1);
if (scrollBarDrag) {
vscrollBar.setBounds(0,0,scrollBar.size,scrollBarLength);
// drag rect for scrollBar
var rect = new createjs.Rectangle(
vscrollBar.x, edgeTop, 0, height-scrollBarLength-edgeTop-edgeBottom
);
vscrollBar.dragBoundary(rect);
vscrollBar.proportion = new zim.Proportion(
rect.y, rect.y+rect.height, 0, -that.scrollYMax
);
vscrollBar.off("pressmove", vEvent);
vEvent = vscrollBar.on("pressmove", function() {
that.dispatchEvent("scrolling");
if (hitArea) {
// move hitarea to display box
hitArea.x = -content.x;
hitArea.y = -content.y;
}
desiredY = content.y = vscrollBar.proportion.convert(vscrollBar.y);
});
}
}
movescrollBars();
clearTimeout(that.d2Timeout);
that.d2Timeout = setTimeout(function(){
if (hscrollBar && hscrollBar.proportion) content.x = hscrollBar.proportion.convert(hscrollBar.x);
if (vscrollBar && vscrollBar.proportion) content.y = vscrollBar.proportion.convert(vscrollBar.y);
}, 50);
clearTimeout(that.dTimeout);
that.dTimeout = setTimeout(function(){setdragBoundary();}, 300);
setdragBoundary();
};
this.resize = function(w, h) {
if (zot(w)) w = width;
if (zot(h)) h = height;
var min = 20;
if (titleBar) min = titleBarLabel.x+titleBarLabel.width+10;
if (w < min) w = min;
if (h < 20) h = 20;
width = w;
height = h;
sizeWindow();
for (var i=0; i 0) {
setdragBoundary();
}
}
}, delay);
}
this.cancelCurrentDrag = function() {
if (that.content) that.content.noDrag(false);
setTimeout(function(){
if (content) {
zim.drag({
obj:content,
currentTarget:true,
localBounds:true,
slide:slide, slideDamp:slideDamp,
slideSnap:(scrollBarH && (swipe===true||swipe=="auto"||swipe=="horizontal")) || (scrollBarV && (swipe===true||swipe=="auto"||swipe=="vertical"))?slideSnap:false
});
if (content.getBounds() && content.getBounds().width > 0) {
setdragBoundary();
}
}
}, 300);
};
var stage, stageEvent;
this.added(function (_stage) {
stage = _stage;
stageEvent = stage.on("stagemousemove", function (e) {
that.windowMouseX = e.stageX/zim.scaX;
that.windowMouseY = e.stageY/zim.scaY;
});
});
if (slide) {
content.on("slidestop", stageUp);
} else {
content.on("mousedown", function() {
content.stage.on("stagemouseup", stageUp, null, true);
});
}
if (cancelCurrentDrag) {
that.blurEvent = function () {
that.cancelCurrentDrag();
stageUp();
};
document.window.addEventListener("blur", that.blurEvent);
}
function stageUp(e) {
zim.Ticker.remove(swipeMovescrollBars);
swipeCheck = false;
if (hCheck) if (scrollBarFade && scrollBarActive) zim.animate(hscrollBar, {alpha:0}, scrollBar.fadeTime);
if (vCheck) if (scrollBarFade && scrollBarActive) zim.animate(vscrollBar, {alpha:0}, scrollBar.fadeTime);
}
if (interactive) {
// dispatches SELECT (click) and HOVEROVER (500 ms) and gives mouseX and mouseY on content
// CLICKS (in the traditional sense rather than a mouseup replacement)
var downLoc;
var downTime;
content.on("mousedown", function(e){stage=e.target.stage; downLoc=e.stageX/zim.scaX; downTime=Date.now();});
content.on("click", function(e){
if (Date.now()-downTime<600 && Math.abs(e.stageX/zim.scaX-downLoc)<5) {
that.contentMouse = content.globalToLocal(e.stageX/zim.scaX, e.stageY/zim.scaY);
that.dispatchEvent("select");
}
});
// HOVER (must stay within thresh pixels for pauseTime ms)
content.on("mouseover", moveOn);
content.on("mouseout", moveOff);
var startTime;
function moveOn() {
startTime=Date.now();
zim.Ticker.add(timeMouse, content.stage);
}
function moveOff() {
if (!hoverOutCalled) {
that.dispatchEvent("hoverout");
hoverOutCalled = true;
}
zim.Ticker.remove(timeMouse);
}
var lastMouseX = 0;
var lastMouseY = 0;
var lastReportX = 0;
var lastReportY = 0;
var pauseTime = 300;
var thresh = 2;
var hoverOutCalled = false;
function timeMouse() {
if (!content.stage) {
if (!hoverOutCalled) {
that.dispatchEvent("hoverout");
hoverOutCalled = true;
}
zim.Ticker.remove(timeMouse);
return;
}
if (Math.abs(lastMouseX-that.windowMouseX) > thresh || Math.abs(lastMouseY-that.windowMouseY) > thresh) {
if (!hoverOutCalled) {
that.dispatchEvent("hoverout");
hoverOutCalled = true;
}
startTime=Date.now();
lastMouseX=that.windowMouseX;
lastMouseY=that.windowMouseY;
} else {
if (Date.now()-startTime > pauseTime) {
if (Math.abs(lastReportX-that.windowMouseX) > thresh || Math.abs(lastReportY-that.windowMouseY) > thresh) {
that.contentMouse = content.globalToLocal(that.windowMouseX, that.windowMouseY);
that.dispatchEvent("hoverover");
lastReportX=that.windowMouseX;
lastReportY=that.windowMouseY;
hoverOutCalled = false;
}
startTime=Date.now();
}
}
}
}
var scrollEvent1;
var scrollEvent2;
var scrollEvent3;
var desiredY = that.scrollY;
that.scrollWindow = function scrollWindow(e) {
if (vCheck && that.stage && that.hitTestPoint(that.windowMouseX, that.windowMouseY) && that.contains(that.stage.getObjectUnderPoint(that.windowMouseX*zim.scaX, that.windowMouseY*zim.scaY))) {
if (zot(e)) e = event;
var delta = e.detail ? e.detail*(-19) : e.wheelDelta;
if (zot(delta)) delta = e.deltaY*(-19);
desiredY += delta;
desiredY = Math.max(-that.scrollYMax, Math.min(0, desiredY));
if (!damp) {
that.scrollY = desiredY;
content.stage.update();
}
}
}
if (scrollWheel) {
window.addEventListener("mousewheel", that.scrollWindow);
window.addEventListener("wheel", that.scrollWindow);
window.addEventListener("DOMMouseScroll", that.scrollWindow);
}
var dampCheck = false;
var dampY;
function makeDamp(obj) {
if (damp && !dampCheck && obj.stage) {
dampCheck = true;
dampY = new zim.Damp(that.scrollY, damp);
that.dampTicker = zim.Ticker.add(function() {
if (swipeCheck) return;
if (!zot(desiredY)) that.scrollY = dampY.convert(desiredY);
}, obj.stage);
}
}
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
if (!value) {
clearTimeout(that.dTimeout);
zim.noDrag(content);
} else {
setDrag();
}
zenable(that, value);
}
});
this._scrollEnabled = true;
Object.defineProperty(that, 'scrollEnabled', {
get: function() {
return that._scrollEnabled;
},
set: function(value) {
if (!value) {
clearTimeout(that.dTimeout);
zim.noDrag(content);
if (scrollBarDrag) {
if (hEvent) hscrollBar.mouseEnabled = false; // hscrollBar.off("pressmove", vEvent);
if (vEvent) vscrollBar.mouseEnabled = false; // vscrollBar.off("pressmove", vEvent);
}
window.removeEventListener("mousewheel", that.scrollWindow);
window.removeEventListener("wheel", that.scrollWindow);
window.removeEventListener("DOMMouseScroll", that.scrollWindow);
} else {
setDrag();
if (scrollBarDrag) {
if (hEvent) hscrollBar.mouseEnabled = true; //hEvent = hscrollBar.on("pressmove", vEvent);
if (vEvent) vscrollBar.mouseEnabled = true; //vEvent = vscrollBar.on("pressmove", vEvent);
}
window.addEventListener("mousewheel", that.scrollWindow);
window.addEventListener("wheel", that.scrollWindow);
window.addEventListener("DOMMouseScroll", that.scrollWindow);
}
that._scrollEnabled = value;
}
});
Object.defineProperty(that, 'scrollX', {
get: function() {
return content.x;
},
set: function(value) {
content.x = value;
clearTimeout(that.d2Timeout);
if (content.zimDragImmediate) content.zimDragImmediate(content.x, content.y);
movescrollBars();
}
});
Object.defineProperty(that, 'scrollY', {
get: function() {
return content.y;
},
set: function(value) {
content.y = value;
clearTimeout(that.d2Timeout);
if (content.zimDragImmediate) content.zimDragImmediate(content.x, content.y);
movescrollBars();
}
});
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function(recursive) {
if (zot(recursive)) recursive = true;
var w = that.cloneProps(new zim.Window(width, height, backgroundColor, originalBorderColor, originalBorderWidth, padding, corner, swipe, scrollBarActive, scrollBarDrag, scrollBar.color, scrollBarAlpha, scrollBarFade, scrollBarH, scrollBarV, slide, slideDamp, slideSnap, interactive, shadowColor, shadowBlur, paddingHorizontal, paddingVertical, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, draggable, boundary, onTop, close, closeColor, cancelCurrentDrag, fullSize, fullSizeColor, resizeHandle, style, group, inherit));
if (recursive) {
that.content.cloneChildren(w.content);
w.update();
}
return w;
};
this.doDispose = function(a,b,disposing) {
if (scrollWheel) {
window.removeEventListener("mousewheel", that.scrollWindow);
window.removeEventListener("wheel", that.scrollWindow);
window.removeEventListener("DOMMouseScroll", that.scrollWindow);
}
if (stageEvent && stage) stage.off("stagemousemove", stageEvent);
if (that.resizeHandle) that.resizeHandle.removeAllEventListeners();
if (that.blurEvent) document.window.removeEventListener("blur", that.blurEvent);
if (typeof timeMouse != "undefined") zim.Ticker.remove(timeMouse);
if (!zot(swipeMovescrollBars)) zim.Ticker.remove(swipeMovescrollBars);
if (!disposing) this.zimContainer_dispose(true);
content = that.content = null;
return true;
};
};
zim.extend(zim.Window, zim.Container, ["clone", "dispose"], "zimContainer", false);
zim.Window.prototype.dispose = function(disposing) {return this.doDispose(null,null,disposing);};
//-58.1
/*--
zim.Page = function(width, height, color, color2, vertical, pattern, scalePattern, cache, style, group, inherit)
Page
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
ZIM Page() is a Container() with Rectangle() backing.
For years, many questions were asked - how to make a page in ZIM.
Now, we have decided to officially answer that! ZIM Page().
An easy way to handle linear gradients is provided as well as a custom background
such as a ZIM Pizzazz pattern.
To keep things brief, Page is expected to fit the stage.
So border, corner, dashed, etc. has been left out.
If the page is smaller and these are desired...
old-school-it and make a Container and add the desired Rectangle.
SEE: https://zimjs.com/cat/page.html
SEE: Docs for ZIM Pages() as well to handle multiple pages.
SEE: ZIM Panel(), ZIM Pane() and ZIM Window() for alternatives.
NOTE A Page object will start with one child or two children if a pattern is specified.
NOTE Do not use Page with Layout as it will overlay the region backgroundColors - instead use a Container
NOTE as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var page = new Page(stageW, stageH, red, pink).addTo();
page.title = new Label("A Page!").loc(100,100,page);
page.content = new Circle().center(page);
page.nav = new Tabs().pos(0,100,CENTER,BOTTOM,page);
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default zimDefaultFrame.width) the width of the Page
but backing is sized to screen.width if no width is provided
height - (default zimDefaultFrame.height) the height of the Page
but backing is sized to screen.height if no height is provided
color - (default zim.light) the color of the page
color2 - (default null) a second color which would form a zim.GradientColor() as the color
vertical - (default true) the direction for the gradient if there is a gradient
pattern - (default null) a DisplayObject that will be added to the page above the backing
For instance, import ZIM pizzazz_03.js and use:
pizzazz.makePattern("slants", series([grey,dark]), 20, 52, 40).alp(.2)
scalePattern - (default "fill") scale the pattern so it fills the window (formerly "bigger" or "outside")
set to false for no scaling or:
"fit" fits inside the Page keeping proportion (formerly "smallest")
"fill" fills the Page keeping proportion (formerly "biggest" or "outside")
"full" keeps both x and y scales - may stretch object (formerly "both")
cache - (default false or true for gradient or pattern) whether the backing and pattern is cached
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
clone(recursive) - makes a copy with properties such as x, y, etc. also copied
recursive (default false) - set to true to copy children of the object (these will not get custom properties, no drag, events, etc.)
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
backing - access the backing Rectangle
pattern - access the pattern object if one is provided
color - get or set the color of the backing Rectangle
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+58.3
zim.Page = function(width, height, color, color2, vertical, pattern, scalePattern, cache, style, group, inherit) {
var sig = "width, height, color, color2, vertical, pattern, scalePattern, cache, style, group, inherit";
var duo; if (duo = zob(zim.Page, arguments, sig, this)) return duo;
z_d("58.3");
this.group = group;
var DS = style===false?{}:zim.getStyle("Page", this.group, inherit);
if (zot(width)) width=DS.width!=null?DS.width:zdf.width;
if (zot(height)) height=DS.height!=null?DS.height:zdf.height;
this.zimContainer_constructor(0,0,width,height,false);
this.type = "Page";
// if (zot(width)) width = screen?screen.width:zdf.width;
// if (zot(height)) height = screen?screen.height:zdf.height;
var that = this;
if (zot(vertical)) vertical=DS.vertical!=null?DS.vertical:true;
if (zot(color)) color=DS.color!=null?DS.color:zim.light;
if (zot(color2)) color2=DS.color2!=null?DS.color2:null;
if (zot(pattern)) pattern=DS.pattern!=null?DS.pattern:null;
if (zot(scalePattern)) scalePattern=DS.scalePattern!=null?DS.scalePattern:"fill";
if (zot(cache)) cache=DS.cache!=null?DS.cache:false;
if (!zot(color2)) {
color = new zim.GradientColor([color, color2], [0,1], 0,0, vertical?0:width, vertical?height:0);
color2 = null;
}
var backing = this.backing = new zim.Rectangle({width:width, height:height, color:color, style:false}).addTo(this);
if (zot(cache) && (!zot(color2) || !zot(pattern))) cache = true;
if (cache) backing.cache();
if (!zot(pattern)) {
this.pattern = pattern.addTo(this);
if (scalePattern) pattern.scaleTo(this, 100, 100, scalePattern).center(this);
if (cache) pattern.cache();
}
Object.defineProperty(that, 'color', {
get: function() {
return color;
},
set: function(value) {
if (zot(value)) value = "black";
color = value;
that.backing.color = value;
}
});
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function(recursive) {
if (zot(recursive)) recursive = false;
if (color.type) color2 = null;
var w = that.cloneProps(new zim.Page(width, height, color, color2, vertical, pattern, scalePattern, cache, style, group, inherit));
if (recursive) {
that.cloneChildren(w);
}
return w;
};
};
zim.extend(zim.Page, zim.Container, ["clone"], "zimContainer", false);
//-58.3
/*--
zim.Layer = function(width, height, titleBar, titleBarContainer, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, borderWidth, borderColor, dashed, transformObject, titleBarWidth, titleBarHeight, titleBarX, titleBarY, titleBarDraggable, close, closeColor, closeBackgroundColor, closeIndicatorColor, anchor, style, group, inherit)
Layer
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Layer is a ZIM Container with transform controls.
ZIM transform() objects have their mousechildren turned off so they can be dragged and transformed.
This means there can be no interactivity inside the transformed object.
Layer provides a solution to nest transformed objects in transformable containers.
It does so by providing a titleBar that can be used to turn on and off the transform of the container
and allow its contents to be transformed when the transform controls of the Layer are turned off.
This is more than just hiding the transform tools but rather removing and adding them.
The Layer titleBar will always remain visible on the stage
If the Layer is moved (not by its titleBar) so that the titleBar hits the edge,
then the titleBar will become anchored to the edge (unless anchor is set to false)
This creates an independent titleBar that can be moved to any location.
The titleBarPos() method can also be used to separate the titleBar at any time.
Drop the titleBar on the top left corner of the Layer or doubleClick it to snap it back on to the layer
NOTE: Layers can be added to a Transform Manager and saved with the persist sytem.
NOTE: Layers can be added to Layers (nested) along with any other type of DisplayObject content.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
SEE: https://zimjs.com/explore/layer.html
EXAMPLE
// adding the Layers above the content will allow pressing Layer titleBar objects inside other Layers
// adding everything right on the stage would not allow pressing titleBars inside other Layers - either way may be best, depending on content
var content = new Container(stageW, stageH).addTo();
var layers = new Container(stageW, stageH).addTo();
// create an outer layer with two inner layers - one holding a circle and the other two circles
var layer0 = new Layer(800, 500, "LAYER 0", layers).center(content);
var layer1 = new Layer(300, 400, "LAYER 1", layers).loc(50,50,layer0);
var circle1 = new Circle(50, pink).center(layer1).transform({visible:false});
var layer2 = new Layer(300, 400, "LAYER 2", layers).pos(50,50,true,false,layer0);
var circle2 = new Circle(50, green).center(layer2).mov(0, -80).transform({visible:false});
var circle3 = new Circle(50, blue).center(layer2).mov(0, 80).transform({visible:false});
// optionally store transforms
var t = new TransformManager([layer0, layer1, layer2, circle1, circle2, circle3], "layersID");
// t.clearPersist("layersID")
timeout(1, function () {
layer2.resetTitleBar();
layer2.turnOn();
// if moving manually, must call resize()
layer2.mov(30);
layer2.resize();
stage.update();
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 500) the width of the Layer Container
height - (default 500) the height of the Layer Container not including the titleBar (which is not in the Container)
titleBar - (default "LAYER") a String or ZIM Label for the titleBar
titleBarContainer - (default null - zdf' stage) a container for the titleBar
can group these with other Layers and hide them all by hiding the container for instance
this also can help layer the titleBars above the content
backgroundColor - (default #eee) the background color of the titleBar
rollBackgroundColor - (default #fff) the roll background color of the titleBar
selectedBackgroundColor - (default #666) the selected background color of the titleBar
color - (default #666) the color of the titleBar text
rollColor - (default #666) the roll color of the titleBar text
selectedColor - (default #ddd) the selected color of the titleBar text
borderWidth - (default 1) the width of the ghost outline when the Layer is not selected
to adjust the transform controls border width use the transformObject parameter and set the borderWidth property
borderColor - (default borderColor) the color of the ghost outline when the Layer is not selected
to adjust the transform controls border color use the transformObject parameter and set the borderColor property
dashed - (default true) the dashed of the ghost outline when the Layer is not selected
to adjust the transform controls border dashed use the transformObject parameter and set the dashed property
transformObject - (default {borderColor:selectedBackgroundColor}) any of the transform parameters as an object literal
certain properties are overwritten by Layer as follows:
{events:true, visible:false, ghostColor:borderColor, ghostWidth:borderWidth, ghostDashed:dashed, ghostHidden:true}
use the transformControls.show() to show the transform controls once the Layer is made for instance:
timeout(100, function(){layer.transformControls.show();}); // a timeout is needed as Layer gets created - sorry.
titleBarWidth - (default 100 + 30 if close) the width of the titleBar. 30 pixels will be added if close is true
titleBarHeight - (default 40) the height of the titleBar
titleBarX - (default null) the starting x position of the titleBar - see also titleBarPos() and resetTitleBar() methods
titleBarY - (default null) the starting y position of the titleBar - see also titleBarPos() and resetTitleBar() methods
titleBarDraggable - (default true) set to false to not let the titleBar be dragged.
this is useful with the titleBarPos() to create a stationary menu for the layers - for instance along the edge like tabs
close - (default true) - set to false to not use the close checkbox
WARNING: without the close checkbox, the user may make the layer bigger than the stage and not be able to deselect the layer
closeColor - (default selectedBackgroundColor) the border of the close checkBox
closeBackgroundColor - (default selectedBackgroundColor) the backgroundColor of the close checkBox
closeIndicatorColor - (default selectedColor) the indicator color of the close checkBox
anchor - (default true) set to false to not anchor the titleBar to the edge if dragged with the Layer (not the titleBar)
with anchor true, the user can dock the titleBar to the edges and then drag them to any desired location
the user can snap the titleBar back on the layer by dropping it on the top left corner of the layer or double clicking the titleBar
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
titleBarPos(x, y, right, bottom) - position the titleBar in the titleBarContainer - returns object for chaining
This will undock the titleBar from the Layer so it can be moved independently
unless titleBarDraggable is set to false
See also titleBarX and titleBarY parameters to start titleBars at a certain position
resetTitleBar() - dock the titleBar back on the Layer - returns object for chaining
toggle(state) - toggle the controls or turn on or off the controls by providing a Boolean state - returns object for chaining
resize(dispatch) - resize the Layer and its children if Layer is manually adjusted - returns object for chaining
for instance, layer.x = 10; layer.resize(); otherwise, the transform controls are broken!
normal layer transforming using the controls automatically resize.
Setting dispatch to true will dispatch a "transformed" event
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied (returns the new waiter for chaining)
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
transformControls - the transform transformControls object - see below for a description
anchor - get or set whether the titleBar will anchor to the edges of the titleBarContainer
toggled - read only if Layer has its transform turned on - or use transformControls.visible
use toggle(state) to toggle controls or pass in true for show controls or false for hide controls
titleBar - access to the ZIM Container that holds the titleBar
titleBarDraggable - get or set whether the titleBar can be dragged
use with titleBarPos() to permanently positing the titleBar
checkBox - access to the ZIM CheckBox that shows when the Layer is active and close is true
button - access to the ZIM Button that makes up the titleBar
label - access to the ZIM Label that is on the Button for the titleBar
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the transformControls property described below for more options.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
TRANSFORM CONTROLS OBJECT
Layer receives a transformControls property
This may be slightly delayed as Layer is prepared on stage
var layer = new Layer().center();
timeout(100, function(){zog(layer.transformControls);}); // will probably do the trick
The transformControls property holds the following:
TRANSFORM CONTROL OBJECT PROPERTIES
visible - read only whether the controls are visible
ghost - read only as to whether the ghost outline is showing - set with showGhost and hideGhost
ghostEnabled - read only as to whether the ghost outline will be turned on and off - set with addGhost and removeGhost
scaleControls - reference to the Container that holds the corner boxes for scaling
stretchXControls - reference to the Container that holds the left and right boxes for stretching
stretchYControls - reference to the Container that holds the top and bottom boxes for stretching
rotateControls - reference to the Container that holds the outer circles for rotating
TRANSFORM CONTROL OBJECT METHODS
hide() - hides the controls - returns object for chaining
show() - shows the controls - returns object for chaining
recordData(toJSON) - returns an object with type, x, y, scaleX, scaleY, rotation, skewX, skewY, visible PROPERTIES
if toJSON (default false) is set to true, the return value is a JSON string
setData(data, fromJSON) - sets the properties to match the data object passed in - this should come from recordData()
if fromJSON (default false) is set to true, it will assume a JSON string is passed in as data
returns object for chaining
remove(noHide) - removes the controls - set noHide true if already hidden
add(noShow) - adds the controls back if then have been removed - set noShow true if not wanting to show
allowToggleOn() - sets the show / hide controls on with click
allowToggleOff() - removes the show / hide controls on with click
showGhost() - show the ghost outline - the ghostWidth or ghostColor must be set in initial parameters
hideGhost() - hide the ghost outline
toggleGhost(state) - if ghost is showing will hide ghost and if ghost is hidden will show ghost
or set state to true to show ghost or false to not show ghost
addGhost() - enable ghost outline functionality - the ghostWidth or ghostColor must be set in initial parameters
removeGhost() - disable ghost outline functionality
disable() - may show the controls if visible but cannot use them
enable() - turns the using of the controls back on
resize(dispatch) - call resize if the object is transformed in ways other than with the controls
set dispatch to true to dispatch a "transformed" event - if manually adjusted this will save to TransformManager
EVENTS
dispatches a "transformed" event when being transformed
the transformed event object has a transformType property
the transformType property has values of "size", "move", "rotate", "stretch", "reg", "reset"
the transformType also might be "resize" if resize(true) is called to dispatch a transformed event
the transformed event object also has a pressup property that is true if on pressup and null if from pressmove
dispatches "transformshow" and "transformhide" events for when click to hide or show controls
If TransformManager() is used there are more events available such as "persistset", etc.
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+58.5
zim.Layer = function(width, height, titleBar, titleBarContainer, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, borderWidth, borderColor, dashed, transformObject, titleBarWidth, titleBarHeight, titleBarX, titleBarY, titleBarDraggable, close, closeColor, closeBackgroundColor, closeIndicatorColor, anchor, style, group, inherit) {
var sig = "width, height, titleBar, titleBarContainer, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, borderWidth, borderColor, dashed, transformObject, titleBarWidth, titleBarHeight, titleBarX, titleBarY, titleBarDraggable, close, closeColor, closeBackgroundColor, closeIndicatorColor, anchor, style, group, inherit";
var duo; if (duo = zob(zim.Layer, arguments, sig, this)) return duo;
z_d("58.5");
this.group = group;
var DS = style===false?{}:zim.getStyle("Layer", this.group, inherit);
if (zot(width)) width=DS.width!=null?DS.width:500;
if (zot(height)) height=DS.height!=null?DS.height:500;
this.zimContainer_constructor(0,0,width,height,false);
this.type = "Layer";
var that = this;
that.distX = 40; // titleBar distance from top left corner of Container
that.distY = 0;
if (zot(titleBar)) titleBar=DS.titleBar!=null?DS.titleBar:"LAYER";
var titleBarOriginal = titleBar;
var titleBarText = titleBar;
var titleBarDefault = true;
if (zot(backgroundColor)) backgroundColor=DS.backgroundColor!=null?DS.backgroundColor:"#eee";
if (zot(rollBackgroundColor)) rollBackgroundColor=DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#fff";
if (zot(selectedBackgroundColor)) selectedBackgroundColor=DS.selectedBackgroundColor!=null?DS.selectedBackgroundColor:"#666";
if (zot(color)) color=DS.color!=null?DS.color:"#666";
if (zot(rollColor)) rollColor=DS.rollColor!=null?DS.rollColor:"#666";
if (zot(selectedColor)) selectedColor=DS.selectedColor!=null?DS.selectedColor:"#ddd";
if (zot(borderWidth)) borderWidth=DS.borderWidth!=null?DS.borderWidth:1;
if (zot(borderColor)) borderColor=DS.borderColor!=null?DS.borderColor:backgroundColor;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
if (zot(dashed)) dashed=DS.dashed!=null?DS.dashed:true;
if (zot(transformObject)) transformObject=DS.titleBar!=null?DS.titleBar:null;
if (zot(titleBarWidth)) titleBarWidth=DS.titleBarWidth!=null?DS.titleBarWidth:100;
var originalTitleBarWidth = titleBarWidth;
if (zot(titleBarHeight)) titleBarHeight=DS.titleBarHeight!=null?DS.titleBarHeight:40;
if (zot(titleBarX)) titleBarX=DS.titleBarX!=null?DS.titleBarX:null;
if (zot(titleBarY)) titleBarY=DS.titleBarY!=null?DS.titleBarY:null;
if (zot(titleBarDraggable)) titleBarDraggable=DS.titleBarDraggable!=null?DS.titleBarDraggable:true;
if (zot(close)) close=DS.close!=null?DS.close:true;
if (zot(closeColor)) closeColor=DS.closeColor!=null?DS.closeColor:selectedBackgroundColor;
if (zot(closeBackgroundColor)) closeBackgroundColor=DS.closeBackgroundColor!=null?DS.closeBackgroundColor:selectedBackgroundColor;
if (zot(closeIndicatorColor)) closeIndicatorColor=DS.closeIndicatorColor!=null?DS.closeIndicatorColor:selectedColor;
if (zot(anchor)) anchor=DS.anchor!=null?DS.anchor:true;
if (!titleBarDraggable) anchor = false;
that.anchor = anchor;
if (close) titleBarWidth += 30;
transformObject = zim.merge({borderColor:selectedBackgroundColor}, transformObject, {events:true, visible:false, ghostColor:borderColor, ghostWidth:borderWidth, ghostDashed:dashed, ghostHidden:true});
// do the defaultFrame thing for the container
if (zot(titleBarContainer)) titleBarContainer=DS.titleBarContainer!=null?DS.titleBarContainer:null;
if (zot(titleBarContainer)) {
if (zdf) {
titleBarContainer = zdf.stage;
} else {
zog("zim Layer(): Please pass in a reference to a container with bounds set.");
return;
}
}
var downCheck = false;
that.active = false;
that.turnOff = function(noHide, noShow) {
that.active = false;
if (close) that.checkBox.visible = false;
that.transformControls.remove();
that.mouseChildren = true;
that.button.backgroundColor = backgroundColor;
that.button.rollBackgroundColor = rollBackgroundColor;
that.button.color = color;
that.button.rollColor = color;
that.transformControls.allowToggleOff();
if (that.resizeChildren) that.resizeChildren();
};
that.turnOn = function() {
that.active = true;
if (close) {
that.checkBox.visible = true;
that.checkBox.checked = true;
}
that.button.backgroundColor = selectedBackgroundColor;
that.button.rollBackgroundColor = selectedBackgroundColor;
that.button.color = selectedColor;
that.button.rollColor = selectedColor;
that.mouseChildren = false;
that.transformControls.add();
that.transformControls.allowToggleOn();
};
var stage;
that.titleBarPos = function(x, y) {
if (!that.titleBar) return;
if (that.titleBar.pos) {
that.titleBar.pos(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]); // ES6 wish
stage.update();
} else {
that.distX = x;
that.distY = y;
}
titleBarDefault = false;
return that;
};
var lastVisible = that.visible;
that.visible = false;
var firstControl;
var timeType = getTIME();
this.added(function (theStage) {
stage = theStage;
that.transform(transformObject); // in case persist is set do this first and wait a little bit with visible false
if (borderWidth >= 0) that.transformControls.hideGhost();
setTimeout(function () {
function firstPoint() {return that.localToLocal(0,0,titleBarContainer);}
that.visible = lastVisible;
if (borderWidth >= 0) {
setTimeout(function(){
that.transformControls.showGhost();
if (that.stage) that.stage.update();
}, 100);
}
stage = theStage;
var titleBar = that.titleBar = new zim.Container(titleBarWidth, titleBarHeight)
.reg(0,titleBarHeight)
.loc(that, null, titleBarContainer)
.mov(that.distX,that.distY);
if (titleBarDraggable) titleBar.drag({all:true, boundary:new zim.Boundary(0,titleBarHeight,titleBarContainer.width-titleBarWidth,titleBarContainer.height-titleBarHeight), localBounds:true});
if (that.distX != 40 || that.distY !=0) {
titleBar.pos(that.distX, that.distY);
}
if (close) {
that.checkBox = new zim.CheckBox({
borderColor:closeColor,
backgroundColor:closeBackgroundColor,
indicatorColor:closeIndicatorColor,
size:20, startChecked:true
}).center(titleBar).pos(0, null, true).change(function () {
that.turnOff(true, true);
});
that.checkBox.visible = false;
}
titleBar.mouseChildren = true;
titleBar.layer = that;
that.resetTitleBar = function() {
that.distX = 40;
that.distY = 0;
titleBarDefault = true;
that.move(true);
if (that.stage) that.stage.update();
};
if (typeof titleBarText === "string" || typeof titleBarText === "number") titleBarText = new zim.Label({
text:titleBarText, color:color, rollColor:rollColor, size:DS.size!=null?DS.size:18,
group:this.group
});
that.label = titleBarText;
that.label.center(titleBar);
that.button = new zim.Button({
shadowBlur:-1,
width:originalTitleBarWidth, height:titleBarHeight-1, label:that.label,
color:color,
rollColor:rollColor,
backgroundColor:backgroundColor,
rollBackgroundColor:rollBackgroundColor,
corner:(DS.corner!=null?DS.corner:0),
inherit:zim.copy(DS)
}).addTo(titleBar);
that.button.on("mousedown", function () {
downCheck = true;
// all other layers get turned off
titleBarContainer.loop(function (bar) {
if (bar && bar != titleBar && bar.layer && bar.layer.turnOff && bar.layer.active) bar.layer.turnOff(true, true);
});
if (!that.active) that.turnOn();
titleBar.top();
});
that.button.on("pressmove", function(){matchLocation();});
that.button.on("pressup", function () {
matchLocation(true);
var point = that.localToLocal(0, 0, titleBarContainer);
that.distX = titleBar.x-point.x;
that.distY = titleBar.y-point.y;
titleBar.top();
downCheck = false;
if (!edgeCheck() && titleBarDraggable) {
var point = that.localToGlobal(0,0);
if (that.button.hitTestPoint(point.x, point.y)) that.resetTitleBar();
}
});
function matchLocation(dispatch) {
if (titleBarDefault && titleBarDraggable) {
var desiredTopLeft = titleBarContainer.localToLocal(titleBar.x-that.distX, titleBar.y-that.distY, that.parent);
var regPoint = that.localToLocal(that.regX, that.regY, that.parent);
var topLeft = that.localToLocal(0,0,that.parent);
that.x = desiredTopLeft.x + (regPoint.x-topLeft.x);
that.y = desiredTopLeft.y + (regPoint.y-topLeft.y);
that.transformControls.resize(dispatch); // TransformManager saves all objects any time a single object changes
recursiveLocation(that);
}
}
function recursiveLocation(obj) {
obj.loop(function (o) {
if (o.type == "Layer") {
if (that.titleBarDraggable) o.move();
if (o.transformControls.ghost) o.transformControls.resize(); // to move ghost
recursiveLocation(o);
}
});
}
that.button.on("dblclick", function () {
if (titleBarDraggable) that.resetTitleBar();
});
that.turnOff();
that.on("transformed", function (e) {
if (e.transformType=="move" || e.transformType=="size" || e.transformType=="stretch" || e.transformType=="rotate") {
if (titleBarDraggable) that.move();
recursiveLocation(that);
}
});
function edgeCheck() {
if (titleBar.x == 0) return true;
if (titleBar.y == titleBar.height) return true;
if (titleBar.x == titleBarContainer.width-titleBar.width) return true;
if (titleBar.y == titleBarContainer.height) return true;
}
that.move = function(override) {
if (!override && !titleBarDefault && that.anchor) {
if (edgeCheck()) return;
}
titleBar.loc(firstPoint()).mov(that.distX, that.distY);
if (titleBar.x < 0) {titleBarDefault=false; titleBar.x = 0;}
if (titleBar.y < titleBar.height) {titleBarDefault=false; titleBar.y = titleBar.height;}
if (titleBar.x > titleBarContainer.width-titleBar.width) {titleBarDefault=false; titleBar.x = titleBarContainer.width-titleBar.width;}
if (titleBar.y > titleBarContainer.height) {titleBarDefault=false; titleBar.y =titleBarContainer.height;}
if (!that.anchor) titleBarDefault = true;
};
that.on("transformhide", function() {
that.turnOff(true, true);
titleBarContainer.loop(function (bar) {
if (bar && bar != titleBar && bar.layer && bar.layer.turnOff && bar.layer.active) bar.layer.turnOff();
});
});
that.resizeChildren = function(dispatch) {
that.transformControls.resize(dispatch);
// if (that.transformControls.visible) that.transformControls.hide();
that.loop(function (obj) {
if (obj.transformControls) {
if (obj.transformControls.visible) obj.transformControls.hide();
if (obj.type == "Layer") {
obj.resizeChildren();
} else {
obj.transformControls.resize();
}
}
});
};
that.resize = function(dispatch) {
that.move();
that.resizeChildren(dispatch);
return that;
};
that.toggled = false;
function setToggled() {
if (that.toggled) {
titleBarContainer.loop(function (bar) {
if (bar && bar != titleBar && bar.layer && bar.layer.turnOff && bar.layer.active) bar.layer.turnOff();
});
that.turnOn();
} else {
titleBar.top();
that.turnOff();
titleBarContainer.loop(function (bar) {
if (bar && bar != titleBar && bar.layer && bar.layer.turnOff && bar.layer.active) bar.layer.turnOff();
});
}
if (that.stage) that.stage.update();
}
that.toggle = function(state) {
if (zot(state)) {
that.toggled = !that.toggled;
} else {
that.toggled = state;
}
setToggled();
return that;
};
Object.defineProperty(that, 'titleBarDraggable', {
get: function() {
return titleBarDraggable;
},
set: function (value) {
titleBarDraggable = value;
if (titleBarDraggable) titleBar.drag({ all: true, boundary: zim.Boundary(0, 40, titleBarContainer.width - titleBarWidth, titleBarContainer.height - titleBarHeight), localBounds: true });
else titleBar.noDrag(false);
}
});
that.stageUpEvent = stage.on("stagemouseup", function () {
if (that.transformControls.visible) titleBar.top();
});
if (!zot(titleBarX) || !zot(titleBarY)) {
titleBarDefault = false;
var x = !zot(titleBarX)?titleBarX:titleBar.x;
var y = !zot(titleBarY)?titleBarY:titleBar.y-titleBarHeight;
that.titleBarStartX = titleBarX;
that.titleBarStartY = titleBarY;
that.titleBarPos(x,y);
var point = that.parent.localToLocal(that.x, that.y, titleBarContainer);
that.distX = titleBar.x-point.x;
that.distY = titleBar.y-point.y;
}
}); // end timeout
}, timeType=="s"?.05:50); // end added
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Layer(width, height, titleBarOriginal, titleBarContainer, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, borderWidth, borderColor, dashed, transformObject, originalTitleBarWidth, titleBarHeight, titleBarX, titleBarY, titleBarDraggable, close, closeColor, closeBackgroundColor, closeIndicatorColor, anchor, style, this.group, inherit));
};
this.dispose = function(a,b,disposing) {
if (that.stageUpEvent) stage.off("stagemouseup", that.stageUpEvent);
if (titleBarContainer) {
titleBarContainer.loop(function (bar) {
bar.layer = null;
});
}
that.transformControls.dispose();
that.transformControls = null;
if (!disposing) this.zimContainer_dispose(true);
that.titleBar.layer = null;
that.titleBar.dispose();
that.checkBox = that.button = null;
titleBar = that.titleBar = transformObject = null;
return true;
};
};
zim.extend(zim.Layer, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-58.5
/*--
zim.Waiter = function(container, speed, foregroundColor, backgroundColor, corner, shadowColor, shadowBlur, fadeTime, style, group, inherit)
Waiter
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Adds a little animated three dot wait widget.
You need to call waiter.show() to show the waiter and waiter.hide() to hide it.
You do not need to add it to the stage - it adds itself centered.
You can change the x and y (with origin and registration point in middle).
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var waiter = new Waiter(stage);
waiter.show(); // show the waiter until assets load
frame.loadAssets("greeting.mp3");
frame.on("complete", function() {
waiter.hide();
frame.asset("greeting.mp3").play();
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
container - (default first frame's stage) the container that holds the waiter
speed - (default .6) cycle time in seconds (also see ZIM TIME constant)
backgroundColor - (default "orange") the background color
foregroundColor - (default "white") the dot color
corner - (default 14) the corner radius of the waiter box
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
shadowColor - (defaults rgba(0,0,0,.3)) set to -1 for no shadow
shadowBlur - (default 14) the blur of the shadow if shadow is set
fadeTime - (default 0) milliseconds to fade in and out
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show() - shows the waiter (returns the waiter for chaining)
hide() - hides the waiter
toggle(state - default null) - shows waiter if hidden and hides waiter if showing (returns the object for chaining)
or pass in true to show waiter or false to hide waiter
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied (returns the new waiter for chaining)
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
display - reference to the waiter backing graphic
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+59
zim.Waiter = function(container, speed, foregroundColor, backgroundColor, corner, shadowColor, shadowBlur, fadeTime, style, group, inherit) {
var sig = "container, speed, foregroundColor, backgroundColor, corner, shadowColor, shadowBlur, fadeTime, style, group, inherit";
var duo; if (duo = zob(zim.Waiter, arguments, sig, this)) return duo;
z_d("59");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Waiter";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
var timeType = getTIME(speed);
if (zot(speed)) speed=DS.speed!=null?DS.speed:timeType=="s"?.6:600; // ms cycle time
if (zot(foregroundColor)) foregroundColor=DS.foregroundColor!=null?DS.foregroundColor:"white";
if (zot(backgroundColor)) backgroundColor=DS.backgroundColor!=null?DS.backgroundColor:"orange";
if (zot(corner)) corner=DS.corner!=null?DS.corner:16;
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:14;
if (zot(fadeTime)) fadeTime=DS.fadeTime!=null?DS.fadeTime:0;
var height = 40;
var numDots = 3;
var r = height*.6/2;
var s = (height-r*2)/2;
var width = numDots*(r*2+s)+s;
this.setBounds(-width/2,-height/2, width, height);
var that = this;
var stage;
var display = this.display = new zim.Shape({style:false});
this.addChild(display);
display.setBounds(0, 0, width, height);
display.regX = width/2;
display.regY = height/2;
var g = display.graphics;
g.f(backgroundColor);
var cc = corner;
if (!Array.isArray(cc)) cc = [corner, corner, corner, corner];
g.rc(0, 0, width, height, cc[0], cc[1], cc[2], cc[3]);
if (shadowColor != -1 && shadowBlur > 0) display.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
display.on("click", function(e) {
// stops the click from going through the display to the background
e.stopImmediatePropagation();
});
var circles = new zim.Container({style:false});
this.addChild(circles);
var dot;
for (var i=0; i 0) {
that.animate({obj:{alpha:0}, time:fadeTime, call:end});
} else {
end();
}
function end() {
if (that.parent) that.parent.removeChild(that);
stage = that.stage;
if (stage) stage.update();
if (that.zimAccessibility) {
var a = that.zimAccessibility;
a.resize(that);
if (accessibilityClicker) accessibilityClicker.focus();
else that.zimTabTag.nextSibling.focus();
setTimeout(function() {a.talk("Waiter has finished.");}, 50);
}
}
that.toggled = false;
return that;
};
var accessibilityClicker;
var timeouts = [];
this.show = function() {
var mess = "zim display - Waiter(): Please pass in a reference to a container with bounds set as first parameter to Waiter";
if (zot(container)) {
if (zdf) {
container = zdf.stage;
} else {
zog(mess);
return;
}
} else if (!container.getBounds) {
zog(mess);
return;
} else if (zot(container.stage)) {
zog("zim display - Waiter(): The container must have a stage property");
return;
}
var dot; var counter=0;
var s = speed*(timeType=="s"?1000:1);
for (var i=0; i 0) {
that.alpha = 0;
that.animate({alpha:1}, fadeTime);
}
if (that.zimAccessibility) {
var a = that.zimAccessibility;
setTimeout(function(){if (a.activatedObject) accessibilityClicker = a.activatedObject.zimTabTag;}, 50);
a.resize(that);
a.talk(that.zimTabTag.getAttribute("aria-label"));
}
that.toggled = true;
return that;
};
that.toggle = function(state) {
if (state===true) that.show();
else if (state===false) that.hide();
else if (that.parent) that.hide();
else that.show();
return that;
};
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Waiter(container, speed, foregroundColor, backgroundColor, corner, shadowColor, shadowBlur, fadeTime, style, this.group, inherit));
};
this.dispose = function(a,b,disposing) {
if (that.ticker) createjs.Ticker.off("tick", that.ticker);
createjs.Tween.removeTweens(that);
that.removeFrom();
for (var i=0; i 0) {
var shadowRect = new zim.Rectangle(width-2, height-2, backgroundColor, null, null, corner, null, null, false).addTo(this);
shadowRect.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
var backing = doBacking(backing);
var cc = corner;
if (!Array.isArray(cc)) cc = [corner, corner, corner, corner];
var cAdjust = (padding+borderWidth/2)*1.2;
var bar = this.bar = new zim.Rectangle(width-(padding+borderWidth/2)*1.8, height-(padding+borderWidth/2)*1.8, foregroundColor, null, null, [cc[0]-cAdjust,cc[1]-cAdjust,cc[2]-cAdjust,cc[3]-cAdjust], null, null, false).center(this);
var mask = this.mask = new zim.Rectangle(width-(padding+borderWidth/2)*1.8, height-(padding+borderWidth/2)*1.8, null, null, null, null, null, null, false).center(this).alp(0).sca(0,1);
bar.setMask(mask);
}
function doBacking(newBacking) {
if (that.backing) {
var index = that.getChildIndex(that.backing);
that.removeChild(that.backing);
} else {
var index = that.numChildren; // may or may not be shadow rect
}
if (that.border) that.removeChild(that.border);
if (!zot(newBacking) && newBacking.type == "Pattern") {
var pattern = newBacking;
var newBacking = that.backing = new zim.Rectangle(width, height, backgroundColor, null, null, corner, null, null, false).addTo(that, index);
newBacking.pattern = pattern;
pattern.center(newBacking);
var bounds = newBacking.getBounds();
pattern.setMask(newBacking.shape);
if (borderWidth) var border = that.border = new zim.Rectangle(width, height, "rgba(0,0,0,0)", borderColor, borderWidth, corner, null, null, false).addTo(that, index+1);
} else {
var newBacking = that.backing = zot(newBacking) ? new zim.Rectangle(width, height, backgroundColor, borderColor, borderWidth, corner, null, null, false).addTo(that, index) : backing.addTo(that, index);
}
return newBacking;
}
that.setBacking = function(backing) {
doBacking(backing);
if (that.stage) that.stage.update();
};
backing.on("click", function(e) {
// stops the click from going through the display to the background
e.stopImmediatePropagation();
});
if (!zot(label)) {
label.scaleX = label.scaleY = .8;
label.startText = label.text;
if (!zot(percentage)) label.text = label.startText + " 0%";
label.center(that);
if (labelPosition == "above") {
label.y -= 60;
} else {
label.y += 60;
}
label.alpha = .8;
}
this.hide = function() {
var stage = that.stage;
if (that.parent) that.parent.removeChild(that);
if (that.backing.type == "Pattern" && that.backing.pauseInterval) that.backing.pauseInterval();
if (stage) stage.update();
if (that.zimAccessibility) {
var a = that.zimAccessibility;
a.resize(that);
if (accessibilityClicker) accessibilityClicker.focus();
else that.zimTabTag.nextSibling.focus();
setTimeout(function() {a.talk("Progress Bar has finished.");}, 50);
}
that.toggled = false;
return that;
};
var accessibilityClicker;
var waiterTimeout;
this.show = function() {
var mess = "zim display - ProgressBar(): Please pass in a reference to a container with bounds set as first parameter of the ProgressBar";
if (zot(container)) {
if (zdf) {
container = zdf.stage;
} else {
zog(mess);
return;
}
} else if (!container.getBounds) {
zog(mess);
return;
} else if (zot(container.stage)) {
zog("zim display - Waiter(): The container must have a stage property");
return;
}
if (that.timeOut) clearTimeout(that.timeOut);
changePercent(0);
if (that.zimActiveLoader) {
that.zimActiveLoader.on("progress", function(e) {
_percent = e.progress*100;
changePercent(_percent);
});
}
that.center(container);
if (that.backing.type == "Pattern" && that.backing.pauseInterval) that.backing.pauseInterval(false);
if (that.zimAccessibility) {
var a = that.zimAccessibility;
setTimeout(function(){if (a.activatedObject) accessibilityClicker = a.activatedObject.zimTabTag;}, 50);
a.resize(that);
a.talk(that.zimTabTag.getAttribute("aria-label"));
}
that.toggled = true;
return that;
};
that.toggle = function(state) {
if (state===true) that.show();
else if (state===false) that.hide();
else if (that.parent) that.hide();
else that.show();
return that;
};
that.run = function(time, close) {
if (!zot(close)) autoHide = close;
if (zot(time)) time=timeType=="s"?3:3000;
checkTIME(time, timeType); // check for warning
var t = time*(timeType=="s"?1000:1);
that.toggle(true);
if (that.runInterval) clearInterval(that.runInterval);
that.percent = 0;
var startTime = Date.now();
that.runInterval = setInterval(function () {
that.percent = (Date.now()-startTime)/t*100;
if (that.percent >= 100) {
that.percent = 100;
clearInterval(that.runInterval);
}
}, 30);
return that;
};
that.dispatched = false;
function changePercent(amount) {
if (barType == "circle") {
bar.graphics
.c()
.mt(0, 0)
.s(foregroundColor)
.ss(borderWidth-padding*2+.5)
.a(0, 0, width, 0, 360*amount/100*Math.PI/180);
} else {
mask.sca(amount/100, 1);
bar.setMask(mask);
}
if (!zot(percentage)) label.text = label.startText + " " + Math.min(Math.round(amount), 100) + "%";
if (autoHide && fastClose && Math.round(amount) >= 100) that.timeOut = setTimeout(function(){that.hide();}, 200);
if (!that.dispatched && Math.round(amount) >= 100) {
that.dispatchEvent("complete");
that.dispatched = true;
setTimeout(function () {
if (that) that.dispatched = false;
}, 100);
}
if (that.stage) that.stage.update();
}
Object.defineProperty(that, 'percent', {
get: function() {
return _percent;
},
set: function(value) {
_percent = value;
changePercent(value);
}
});
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.ProgressBar(barType, foregroundColor, backgroundColor, borderColor, borderWidth, padding, label, color, labelPosition, percentage, corner, shadowColor, shadowBlur, backing, delay, fastClose, container, autoHide, style, this.group, inherit));
};
this.dispose = function(a,b,disposing) {
if (that.backing.type == "Pattern" && that.backing.clearInterval) that.backing.clearInterval();
if (that.runInterval) clearInterval(that.runInterval);
if (!disposing) this.zimContainer_dispose(true);
return true;
};
};
zim.extend(zim.ProgressBar, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-59.5
/*--
zim.Indicator = function(width, height, num, foregroundColor, backgroundColor, borderColor, borderWidth, backdropColor, corner, indicatorType, fill, scale, lightScale, interactive, shadowColor, shadowBlur, selectedIndex, style, group, inherit)
Indicator
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A row of dots or squares that can be used to indicate a step, page, level, score, etc.
The indicator can be used as an input as well but often these are small so may not be best to rely on.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var lights = new Indicator({fill:true});
lights.selectedIndex = 0; // set the first light on
lights.center();
stage.on("stagemousedown", function() {
// increase the indicator lights each click (then start over)
lights.selectedIndex = (lights.selectedIndex+1) % lights.num;
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 100) width of indicator
height - (default 50) height of indicator
num - (default 6) the number of lights
foregroundColor - (default "orange") color of the light(s) turned on
backgroundColor - (default "grey") color of the light(s) turned off
borderColor - (default -1 for no border) border color of lights and backdrop (if backdrop)
borderWidth - (default 1 if stroke is set) the size of the stroke in pixels
backdropColor - (default -1 for no backdrop) backdrop rectangle around lights
corner - (default 0) the corner radius if there is a backdropColor provided
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
indicatorType - (default "dot" or "circle") can also be "box" or "square"
fill - (default false) set to true to fill in lights to the left of the selectedIndex
scale - (default 1) for all the lights including spacing
lightScale - (default 1) scale for each light - keeping the spacing unchanged
interactive - (default false) set to true to make lights clickable
shadowColor - (default rgba(0,0,0,.3)) set to -1 for no shadow
shadowBlur - (default 5) the shadow blur if shadow is set
selectedIndex - (default 0) - set the selectedIndex at start
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedIndex - gets or sets the current index of the indicator
num - the assigned num value (how many light objects) (read only)
backdrop - gives access to the backdrop if there is one Rectangle
lights - an array of the light objects (zim Circle or Rectangle objects)
lightsContainer - gives access to the lights createjs.Container with its Circle or Rectangle children
enabled - set to false to disable component
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event if press is true and indicator is pressed on and lights change
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+60
zim.Indicator = function(width, height, num, foregroundColor, backgroundColor, borderColor, borderWidth, backdropColor, corner, indicatorType, fill, scale, lightScale, interactive, shadowColor, shadowBlur, selectedIndex, style, group, inherit) {
var sig = "width, height, num, foregroundColor, backgroundColor, borderColor, borderWidth, backdropColor, corner, indicatorType, fill, scale, lightScale, interactive, shadowColor, shadowBlur, selectedIndex, style, group, inherit";
var duo; if (duo = zob(zim.Indicator, arguments, sig, this)) return duo;
z_d("60");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Indicator";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:300;
if (zot(height)) height = DS.height!=null?DS.height:50;
if (zot(num)) num = DS.num!=null?DS.num:6;
if (zot(foregroundColor)) foregroundColor = DS.foregroundColor!=null?DS.foregroundColor:"#f58e25";
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#666";
if (backgroundColor < 0) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"rgba(0,0,0,.01)";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(backdropColor)) backdropColor = DS.backdropColor!=null?DS.backdropColor:-1;
if (zot(corner)) corner = DS.corner!=null?DS.corner:0;
if (zot(indicatorType)) indicatorType = DS.indicatorType!=null?DS.indicatorType:"dot";
if (zot(fill)) fill = DS.fill!=null?DS.fill:false;
if (zot(scale)) scale = DS.scale!=null?DS.scale:1;
if (zot(lightScale)) lightScale = DS.lightScale!=null?DS.lightScale:1;
if (zot(interactive)) interactive = DS.interactive!=null?DS.interactive:false;
if (zot(shadowColor)) shadowColor = DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur = DS.shadowBlur!=null?DS.shadowBlur:5;
var eventType = (!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click";
var that = this;
this.lights = [];
var myValue;
var indicator = new zim.Container({style:false});
if (backdropColor != -1) {
var backing = that.backdrop = new zim.Rectangle(width, height, backdropColor, borderColor, borderWidth, corner, null, null, false);
this.addChild(backing);
}
var lights = this.lightsContainer = new zim.Container({style:false});
this.addChild(lights);
var light;
var size = height * .5;
var space = width / (num+1);
var hitArea = new createjs.Shape();
if (indicatorType == "square" || indicatorType == "box") {
hitArea.graphics.f("black").dr(-space/2/lightScale+size/2, -height/2+size/2, space/lightScale, height);
} else {
hitArea.graphics.f("black").dr(-space/2/lightScale, -height/2, space/lightScale, height);
}
for (var i=0; i 0) lights.shadow = new createjs.Shadow(shadowColor, 2, 2, shadowBlur);
if (interactive) {
lights.cursor = "pointer";
var lightsEvent = lights.on(eventType, function(e) {
if (myValue == e.target.znum) return;
myValue = e.target.znum;
setLights(myValue);
that.dispatchEvent("change");
});
}
lights.scaleX = lights.scaleY = scale;
function setLights(v) {
if (v >= num) v = -1; // out of range - don't let it fill up
var c;
for (var i=0; i that.height-that.selected.height) that.animateTo(that.selectedIndex,timeType=="ms"?100:.1);
} else {
var position = that.selected.x+that.scrollX;
if (position < 0 || position > that.width-that.selected.width) that.animateTo(that.selectedIndex,timeType=="ms"?100:.1);
}
},100);
that.dispatchEvent("change");
})
this.getItemIndex = function(item) {
return that.items.indexOf(item);
};
this.animateTo = function(index, timePerItem) {
if (zot(index)) index = 0;
if (zot(timePerItem)) timePerItem = .05;
var timeType = getTIME(timePerItem);
that.selectedIndex = index;
var newPos = getScrollPosition(index);
if (vertical) {
var itemsToTravel = Math.abs(that.scrollY-newPos)/that.itemHeight;
that.animate({scrollY:newPos}, itemsToTravel*timePerItem/(timeType=="s"?1:1000));
// that.scrollY = newPos;
} else {
var itemsToTravel = Math.abs(that.scrollX-newPos)/that.itemWidth;
that.animate({scrollX:newPos}, itemsToTravel*timePerItem/(timeType=="s"?1:1000));
// that.scrollX = newPos;
}
return that;
};
this.addAt = function(items, index, style, clone) {
if (zot(items)) return that;
if (items.type == "ListItem") {
items.width = width-spacing*2;
} else { // watch items could be an array (good) or container (bad)
if (Array.isArray(items)) {
zim.loop(items, function(item) {
if (item.type == "ListItem") item.width = width-spacing*2;
});
}
}
if (items.clone) {
that.tabs.addAt(clone?items.clone():items, index, style);
} else {
that.tabs.addAt(zim.copy(items, clone), index, style);
}
// var b = tabs.getBounds();
// tabs.setBounds(0,0,vertical?b.width:(b.width+spacing*2+4),vertical?(b.height+spacing*2+4):b.height);
// that.content.x = 0; // why go back to 0? Changed in Cat 01
// that.content.y = 0;
that.update();
return that;
};
this.removeAt = function(num, index) {
that.tabs.removeAt(num, index);
_selectedIndex = that.tabs.selectedIndex;
var b = tabs.getBounds();
tabs.setBounds(0,0,b.width,b.height);
// that.content.x = 0; // why go back to 0? Changed in Cat 01
// that.content.y = 0;
that.update();
return that;
};
if (list[0]=="%-&" && list.length==1) that.removeAt(1,0);
this.clear = function() {
that.tabs.removeAt(that.length, 0);
that.content.x = 0;
that.content.y = 0;
that.update();
return that;
};
this.setCheck = function(index, type) {
if (zot(index)) index = 0;
if (zot(type)) type = true;
that.items[index].checkBox.checked = type;
that.items[index].content.zimOut();
};
this.getCheck = function(index) {
if (zot(index)) index = 0;
return that.items[index].checkBox.checked;
};
this.setChecks = function(type) {
zim.loop(that.items, function (item) {
item.checkBox.checked = type;
item.content.zimOut();
});
return that;
};
Object.defineProperty(that, 'items', {
get: function() {
return that.tabs.buttons;
},
set: function(value) {
if (zon) zogy("List() - items is read only - use addAt() and removeAt() to change");
}
});
Object.defineProperty(that, 'list', {
get: function() {
return that.tabs.buttons;
},
set: function(value) {
if (zon) zogy("List() - list is read only - use addAt() and removeAt() to change");
}
});
Object.defineProperty(that, 'length', {
get: function() {
return that.tabs.buttons.length;
},
set: function(value) {
if (zon) zogy("List() - length is read only");
}
});
Object.defineProperty(that, 'selectedIndex', {
get: function() {
return _selectedIndex;
},
set: function(value) {
tabs.selectedIndex = value;
// that.text = tabs.text;
that.label = tabs.label;
that.selected = tabs.selected;
_selectedIndex = value;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
if (currentSelected) that.selectedIndex = 0;
Object.defineProperty(that, 'selectedIndexPlusPosition', {
get: function() {
return _selectedIndex;
},
set: function(value) {
that.selectedIndex = value;
_selectedIndex = value;
if (vertical) that.scrollY = getScrollPosition(value)-2; // in window?
else that.scrollX = getScrollPosition(value);
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
function getScrollPosition(index) {
// var w = (that.itemWidth+spacing)*(vertical?1:that.length);
// var h = (that.itemHeight+spacing)*(vertical?that.length:1);
// that.tabs.setBounds(w, h);
if (vertical) {
var newY = -(that.itemHeight+spacing)*index + height/2 - that.itemHeight/2;
if ((that.itemHeight+spacing)*that.length < height) newY = 0;
if (newY > 0) newY = 0;
if ((that.itemHeight+spacing)*that.length > height && newY < -that.tabs.height+height-paddingVertical*2) newY = -that.tabs.height+height-paddingVertical*2;
return newY;
} else {
var newX = -(that.itemWidth+spacing)*index + width/2 - that.itemWidth/2;
if ((that.itemWidth+spacing)*that.length < width) newX = 0;
if (newX > 0) newX = 0;
if ((that.itemWidth+spacing)*that.length > width && newX < -that.tabs.width+width-paddingHorizontal*2) newX = -that.tabs.width+width-paddingHorizontal*2;
return newX;
}
}
Object.defineProperty(that, 'text', {
get: function() {
if (that.label) return that.label.text;
return null;
},
set: function(value) {
if (that.label) that.label.text = value;
}
});
Object.defineProperty(that, 'currentValue', {
get: function() {
if (that.label) return that.label.text;
return null;
},
set: function(value) {
var answer = zim.loop(that.list, function (l, i) {
var ll;
if (l.label) ll = l.label.text;
if (l.type == "Label") ll = l.text;
var re = new RegExp(value, "i");
if (ll && ll.match(re)) return i;
});
if (answer!==true) that.selectedIndexPlusPosition = answer;
}
});
Object.defineProperty(that, 'itemDown', {
get: function() {
return that.tabs.buttonDown;
},
set: function(value) {
}
});
Object.defineProperty(that, 'itemsText', {
get: function() {
var a = [];
for (var i=0; i0?"list":"number";
if (zot(min)) min=DS.min!=null?DS.min:0;
if (zot(max)) max=DS.max!=null?DS.max:10;
if (zot(step)) step=DS.step!=null?DS.step:1;
if (zot(step2)) step2=DS.step2!=null?DS.step2:step;
if (zot(arrows2) && step2 != step && stepperType == "number") arrows2=DS.arrows2!=null?DS.arrows2:true;
if (zot(arrows2Scale)) arrows2Scale=DS.arrows2Scale!=null?DS.arrows2Scale:.5;
if (zot(keyEnabled)) keyEnabled = DS.keyEnabled!=null?DS.keyEnabled:true;
if (zot(keyArrows)) keyArrows = DS.keyArrows!=null?DS.keyArrows:true;
if (zot(rightForward)) rightForward = DS.rightForward!=null?DS.rightForward:true;
if (zot(downForward)) downForward = DS.downForward!=null?DS.downForward:(stepperType=="number"?false:true);
var that = this;
var index;
var height = 100;
var boxSpacing = height/4;
backgroundColor = zik(backgroundColor);
var actualStep = step; // toggle between step and step2
var numVal;
var numDir = 1;
var letterVal;
var decimals;
if (stepperType == "number") {
min = Number(min);
max = Number(max);
if (min == NaN) min = 0;
if (max == NaN) max = 100;
if (max < min) {
numDir = -1;
var temp = max; // one day ES6
max = min;
min = temp;
numVal = max;
} else {
numVal = min;
}
this.min = min;
this.max = max;
if (0 > min && 0 < max) numVal = 0;
step = Math.abs(step);
decimals = Math.max(getDecimals(step), getDecimals(step2));
} else if (stepperType == "letter") {
list = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
if (typeof min != "string") min = "A";
if (typeof max != "string") max = "Z";
min = min.substr(0,1).toUpperCase();
max = max.substr(0,1).toUpperCase();
var startLetter = list.indexOf(min);
if (startLetter < 0) {min = "A"; startLetter = 0;}
var endLetter = list.indexOf(max);
if (endLetter < 0) {max = "Z"; endLetter = list.length;}
if (endLetter < startLetter) {
list.reverse();
startLetter = list.length-1-startLetter;
endLetter = list.length-1-endLetter;
}
list = list.splice(startLetter, endLetter-startLetter+1);
} else {
stepperType = "list";
}
function getDecimals(num) {
var decimals = String(num).split(".")[1];
if (decimals) {decimals = decimals.length;} else {decimals = 0;}
return decimals;
}
var rawEvent;
var rawX = 0;
var rawY = 0;
if (draggable) {
this.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
this.stage.mouseMoveOutside = true;
rawX = e.rawX/zim.scaX;
rawY = e.rawY/zim.scaY;
rawEvent = this.stage.on("stagemousemove", function(e){
rawX = e.rawX/zim.scaX;
rawY = e.rawY/zim.scaY;
});
}, null, true);
}
this.label = label;
label.mouseChildren = false;
label.mouseEnabled = false;
var holdCheck = false;
var delayTimeout;
var speedTimeout;
var roundTimeout;
var clickCheck = false;
var prev, arrowPrev, next, arrowNext, prev2, arrowPrev2, next2, arrowNext2;
var holdX;
var holdY;
var proportion;
if (arrows) {
prev = this.containerPrev = new zim.Container({style:false});
this.addChild(prev);
arrowPrev = this.arrowPrev = new zim.Triangle(height, height*.8, height*.8, backgroundColor, null, null, null, null, null, null, null, false);
if (shadowColor != -1 && shadowBlur > 0) prev.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
prev.addChild(arrowPrev);
prev.expand();
prev.cursor = "pointer";
prev.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
actualStep = step;
var val = vertical?(downForward?1:-1):(rightForward?-1:1);
doStep(val);
go(val, null, null, e.stageX/zim.scaX, e.stageY/zim.scaY);
});
if (hold) prev.on("pressup", goEnd);
if (vertical) {
prev.rotation = 180;
prev.x = width/2;
if (display) {
prev.y = prev.height + boxSpacing + height + prev.height/2 + boxSpacing;
} else {
prev.y = prev.height * 2;
}
} else {
prev.rotation = -90;
prev.x = prev.height/2;
prev.y = prev.width/2;
}
}
if (display) {
var box = this.textBox = new zim.Rectangle(width, height, backgroundColor, borderColor, borderWidth, corner, null, null, false);
box.cursor = "pointer";
this.addChild(box);
if (shadowColor != -1 && shadowBlur > 0) box.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
if (arrows) {
if (vertical) {
if (arrows) box.y = arrowPrev.height + boxSpacing;
} else {
if (arrows) box.x = arrowPrev.height + boxSpacing;
}
}
this.addChild(label);
if (list.length > 0) {
// index = Math.floor(list.length/2)
index = 0;
label.text = list[index];
}
label.center(that);
var lastValue;
box.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
lastValue = that.currentValue;
if (press) doStep(1);
go(1, true, null, e.stageX/zim.scaX, e.stageY/zim.scaY); // do decimals from box
// if (stepperType == "number") {
// clearTimeout(roundTimeout);
// clickCheck = true;
// roundTimeout = setTimeout(function() {
// clickCheck = false;
// }, 200);
// }
});
box.on("pressup", function() {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
// if (clickCheck) {
// numVal = Math.ceil(numVal);
// setLabel(numVal, numVal);
// if (that.currentValue != lastValue) that.dispatchEvent("change");
// lastValue = that.currentValue;
// }
});
} else {
if (list.length > 0) {
index = 0;
}
}
if (arrows) {
next = this.containerNext = new zim.Container({style:false});
this.addChild(next);
arrowNext = this.arrowNext = new zim.Triangle(height, height*.8, height*.8, backgroundColor, null, null, null, null, null, null, null, false);
if (shadowColor != -1 && shadowBlur > 0) next.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
next.addChild(arrowNext);
next.expand();
next.cursor = "pointer";
next.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
actualStep = step;
var val = vertical?(downForward?-1:1):(rightForward?1:-1);
doStep(val);
go(val, null, null, e.stageX/zim.scaX, e.stageY/zim.scaY);
});
if (hold) next.on("pressup", goEnd);
if (vertical) {
next.rotation = 0;
next.x = width/2;
next.y = next.getBounds().height/2;
} else {
next.rotation = 90;
if (display) {
next.x = box.x + box.getBounds().width + next.getBounds().height/2 + boxSpacing;
} else {
next.x = prev.x + prev.getBounds().width;
}
next.y = next.getBounds().width/2;
}
}
// pressdown and move mouse changes speed and direction of stepper
function go(dir, both, dec, stageX, stageY) {
if (hold) {
holdX = stageX;
holdY = stageY;
if (holdX == 0) holdX = 1;
if (holdY == 0) holdY = 1;
if (!draggable) dragSensitivity = 1;
var hs = holdSpeed*(timeType=="s"?1000:1);
var hd = holdDelay*(timeType=="s"?1000:1);
var dragInput = hs;
proportion = new zim.Proportion(0, dragRange, hs, hs*dragSensitivity);
delayTimeout = setTimeout(function() {
holdCheck=true;
function doHold() {
speedTimeout = setTimeout(function() {
var dragDir = dir;
if (draggable) {
// only change direction if outside of 10 pixels from where pressed
var diffX = Math.abs(rawX - holdX);
var diffY = Math.abs(rawY - holdY);
if (vertical) {
if (!both && !dec) diffX = 0; // don't do decimals
if (dec) diffY = 0;
} else {
if (!both && !dec) diffY = 0; // don't do decimals
if (dec) diffX = 0;
}
if (diffX >= 10 || diffY >= 10) {
if (diffX > diffY) {
actualStep = vertical?step2:step;
dragDir = rawX - holdX > 0 ? 1 : -1;
if (!rightForward) dragDir*-1;
dragInput = proportion.convert(Math.abs(holdX-rawX));
} else {
actualStep = vertical?step:step2;
dragDir = rawY - holdY > 0 ? 1 : -1;
if (stepperType == "number" || !downForward) {
dragDir *= -1;
}
dragInput = proportion.convert(Math.abs(holdY-rawY));
}
}
}
doStep(dragDir);
doHold();
}, dragInput);
}
doHold();
}, hd);
}
}
if (hold && display) box.on("pressup", goEnd);
function goEnd() {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
holdCheck = false;
clearTimeout(delayTimeout);
clearTimeout(speedTimeout);
}
if (arrows2) { // step2 arrows
prev2 = this.prev2 = new zim.Container({style:false});
arrowPrev2 = this.arrowPrev2 = new zim.Triangle(height, height*.8, height*.8, "rgba(0,0,0,.2)", backgroundColor, 2, null, null, null, null, null, false);
prev2.addChild(arrowPrev2);
prev2.expand();
prev2.cursor = "pointer";
prev2.sca(arrows2Scale);
prev2.alpha = .5;
prev2.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
actualStep = step2;
var val = vertical?(rightForward?-1:1):(downForward?1:-1);
doStep(val);
go(val, null, true, e.stageX/zim.scaX, e.stageY/zim.scaY);
});
if (hold) prev2.on("pressup", goEnd);
next2 = this.next2 = new zim.Container({style:false});
arrowNext2 = this.arrowNext2 = new zim.Triangle(height, height*.8, height*.8, "rgba(0,0,0,.2)", backgroundColor, 2, null, null, null, null, null, false);
next2.addChild(arrowNext2);
next2.expand();
next2.cursor = "pointer";
next2.sca(arrows2Scale);
next2.alpha = .5;
next2.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
actualStep = step2;
var val = vertical?(rightForward?1:-1):(downForward?-1:1);
doStep(val);
go(val, null, true, e.stageX/zim.scaX, e.stageY/zim.scaY);
});
if (hold) next2.on("pressup", goEnd);
if (vertical) {
prev2.y = this.height / 2;
prev2.x = -prev2.width / 2 - boxSpacing*Math.max(.2, Math.min(1, arrows2Scale));
prev2.rotation = 270;
next2.y = this.height / 2;
next2.x = this.width + next2.width/2 + boxSpacing*Math.max(.2, Math.min(1, arrows2Scale));
next2.rotation = 90;
} else {
next2.x = this.width / 2;
next2.y = -next2.height / 2 - boxSpacing*Math.max(.2, Math.min(1, arrows2Scale));
next2.rotation = 0;
prev2.x = this.width / 2;
prev2.y = this.height + prev2.height/2 + boxSpacing*Math.max(.2, Math.min(1, arrows2Scale));
prev2.rotation = 180;
}
this.addChild(prev2, next2);
}
// needed in setLabel()
Object.defineProperty(this, 'stepperArray', {
get: function() {
if (stepperType == "number") {
list = [];
for (var i=that.min; i<=that.max; i+=Math.min(step, step2)) {
list.push(zim.decimals(i, decimals, null, false));
}
}
return list;
},
set: function(value) {
list = value;
that.selectedIndex = that.selectedIndex;
}
});
Object.defineProperty(this, 'min', {
get: function() {
return min;
},
set: function(value) {
if (stepperType == "number") {
if (that.currentValue < value) that.currentValue = value;
min = value;
that.selectedIndex = that.selectedIndex;
} else {
min = value;
}
}
});
Object.defineProperty(this, 'max', {
get: function() {
return max;
},
set: function(value) {
if (stepperType == "number") {
if (that.currentValue > value) that.currentValue = value;
max = value;
that.selectedIndex = that.selectedIndex;
} else {
max = value;
}
}
});
setLabel(stepperType=="number"?numVal:list[index], stepperType=="number"?numVal:index);
function doStep(n) {
var text;
var nextIndex;
if (stepperType == "number") {
var lastNumVal = numVal;
numVal += actualStep * n * numDir;
numVal = zim.decimals(numVal, decimals);
if (!continuous) {
if (numVal > that.max) {
numVal = step==1?that.max:lastNumVal;
if (display) box.cursor = "default";
} else {
if (display) box.cursor = "pointer";
}
if (numVal < that.min) {
numVal = step==1?that.min:lastNumVal;
}
} else {
if (numVal > that.max) {
numVal = that.min;
} else if (numVal < that.min) {
numVal = that.max;
}
}
} else {
nextIndex = index + n;
if (!continuous) {
if (nextIndex > list.length-1) {
if (display) box.cursor = "default";
return;
} else {
if (display) box.cursor = "pointer";
}
if (nextIndex < 0) return;
} else {
if (nextIndex > list.length-1) nextIndex = 0;
if (nextIndex < 0) nextIndex = list.length-1;
}
index = nextIndex;
}
setLabel(stepperType=="number"?numVal:list[index], stepperType=="number"?numVal:index);
if (that.currentValue != lastValue) that.dispatchEvent("change");
lastValue = that.currentValue;
}
Object.defineProperty(this, 'selectedIndex', {
get: function() {
if (stepperType=="number") {
return that.stepperArray.indexOf(that.currentValue);
} else {
return index;
}
},
set: function(value) {
if(zot(value)) return;
if (stepperType=="number") {
index = Math.min(that.stepperArray.length-1, Math.max(0, value));
numVal = that.stepperArray[index];
setLabel(numVal, numVal);
} else {
value = Math.min(list.length-1, Math.max(0, value));
index = value;
setLabel(list[index], index);
}
}
});
Object.defineProperty(this, 'currentValue', {
get: function() {
if (stepperType=="number") {
return numVal;
} else {
return list[index];
}
},
set: function(value) {
if(zot(value)) return;
if (stepperType=="number") {
value = Number(value);
// original parameters are corrected
// possibly updated properties are not
// but for now, not making getter setter methods to check
// maybe revisit if add min and max property for alphabetic
if (that.max > that.min) {
if (value > that.max || value < that.min) return;
} else {
if (value < that.max || value > that.min) return;
}
var newIndex = that.stepperArray.indexOf(value);
if (newIndex < 0) return;
index = newIndex;
numVal = that.stepperArray[index];
setLabel(numVal, numVal);
} else {
if (list.indexOf(value) > -1) {
value = list.indexOf(value);
} else {return;}
if (value == that.selectedIndex) return;
index=value;
setLabel(list[index], index);
}
}
});
Object.defineProperty(this, 'currentValueEvent', {
get: function() {
return that.currentValue;
},
set: function(value) {
if (String(value) != String(that.currentValue)) {
that.currentValue = value;
that.dispatchEvent("change");
}
}
});
Object.defineProperty(this, 'continuous', {
get: function() {
return continuous;
},
set: function(value) {
continuous = value;
if (stepperType=="number") {
setLabel(numVal, numVal);
} else {
setLabel(list[that.selectedIndex], that.selectedIndex);
}
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
if (value) {
if (stepperType=="number") {
setLabel(numVal, numVal);
} else {
setLabel(list[that.selectedIndex], that.selectedIndex);
}
window.addEventListener("keydown", that.keyDownEvent);
} else {
greyPrev();
greyNext();
window.removeEventListener("keydown", that.keyDownEvent);
if (display) label.mouseChildren = false;
if (display) label.mouseEnabled = false;
}
if (next && ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && next.stage)) {
next.stage.update();
} else if (label && ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && label.stage)) {
label.stage.update();
}
}
});
if (typeof KEYFOCUS !== typeof undefined) zim.KEYFOCUS = KEYFOCUS;
Object.defineProperty(this, 'keyFocus', {
get: function() {
return zim.KEYFOCUS == that;
},
set: function(value) {
zim.KEYFOCUS = that;
}
});
if (!zim.KEYFOCUS) setFocus();
this.on("mousedown", function() {setFocus();});
function setFocus() {that.keyFocus = true; var d=document.activeElement; if (d) d.blur();}
function setArrows() {
prev.alpha = 1;
arrowPrev.color = backgroundColor;
prev.cursor = "pointer";
next.alpha = 1;
arrowNext.color = backgroundColor;
next.cursor = "pointer";
if (!continuous) {
if (stepperType == "number") {
if (index == that.min) {
if (numDir > 0) {greyPrev();} else {greyNext();}
}
if (index == that.max) {
if (numDir > 0) {greyNext();} else {greyPrev();}
}
} else {
if (index == 0) vertical?greyNext():greyPrev();
if (index == list.length-1) vertical?greyPrev():greyNext();
}
}
}
function setLabel(text, n) {
index = n;
if (display) {
if (stepperType == "number") {
if (text != 0 && decimals > 0) {
text = zim.decimals(text, decimals, true);
}
}
label.text = text;
label.center(that);
// label.x = box.x+box.getBounds().width/2;
// label.y = box.y+(box.getBounds().height-label.getBounds().height)/2;
}
if (arrows) setArrows();
if (next && ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && next.stage)) {
next.stage.update();
} else if (label && ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && label.stage)) {
label.stage.update();
}
if (that.zimAccessibility) that.zimAccessibility.changeTitle(that, null, true);
}
function greyPrev() {
if (!arrows) return;
prev.alpha = .8;
arrowPrev.color = "#aaa";
prev.cursor = "default";
}
function greyNext() {
if (!arrows) return;
next.alpha = .8;
arrowNext.color = "#aaa";
next.cursor = "default";
}
var pressCheck = false;
var decimalCheck = false;
var negativeCheck = false;
var keyRestartCheck = true;
var lastKeyNum = "";
this.on("mousedown", function() {
keyRestartCheck = true;
lastKeyNum = "";
if (that.zimAccessibility && that.zimAccessibility.aria) return;
that.focus = true;
pressCheck = true;
decimalCheck = false;
negativeCheck = false;
});
this.keyDownEvent = function(e) {
if (!that.stage) return;
if ((that.zimAccessibility && that.focus) || (!that.zimAccessibility && that.keyFocus)) {
if (!e) e = event;
var k = e.keyCode;
if (keyArrows) {
if (k >= 37 && k <= 40) {
var forwardVertical = downForward?40:38;
var forwardHorizontal = rightForward?39:37;
var backwardVertical = downForward?38:40;
var backwardHorizontal = rightForward?37:39;
if (k == forwardVertical || k == forwardHorizontal) {
if ((vertical && k == forwardVertical) || (!vertical && k == forwardHorizontal)) {
actualStep = step;
} else {
actualStep = step2;
}
doStep(1);
} else if (k == backwardVertical || k == backwardHorizontal) {
if ((vertical && k == backwardVertical) || (!vertical && k == backwardHorizontal)) {
actualStep = step;
} else {
actualStep = step2;
}
doStep(-1);
}
}
}
if (keyEnabled) {
if (stepperType=="number") { // 48-57, 96-105 190. 173-
var num = null;
var other = null;
if (k == 8) { // backspace
var arr = String(lastKeyNum).split("");
arr.pop();
var num = arr.pop();
lastKeyNum = arr.join("");
}
if (!e.shiftKey && k>=48 && k<=57) {
num = k-48;
} else if (k>=96 && k<=105) {
num = k-96;
} else if (k==190) {
lastKeyNum = String(lastKeyNum) + ".";
other = true;
} else if (k==173 || k==189) {
that.currentValue = that.currentValue * -1;
if (that.currentValue != lastValue) that.dispatchEvent("change");
lastValue = that.currentValue;
negativeCheck = !negativeCheck;
} else if (k == 46) { // delete
keyRestartCheck = true;
lastKeyNum = "";
}
if (zot(num) && zot(other)) {
keyRestartCheck = true;
lastKeyNum = "";
return;
}
if (zot(num)) return;
if (keyRestartCheck) {
keyRestartCheck = false;
lastKeyNum = num;
} else {
lastKeyNum = num = Number(lastKeyNum + "" + num);
}
if (num < min || num > max) return;
that.currentValue = num;
if (that.currentValue != lastValue) that.dispatchEvent("change");
lastValue = that.currentValue;
} else {
keyRestartCheck = true;
lastKeyNum = "";
that.currentValue = String.fromCharCode(e.keyCode);
if (that.currentValue != lastValue) that.dispatchEvent("change");
lastValue = that.currentValue;
}
}
}
};
window.addEventListener("keydown", this.keyDownEvent);
this.next = function() {
doStep(1);
};
this.prev = function() {
doStep(-1);
};
if (zot(selectedIndex)) selectedIndex=DS.selectedIndex!=null?DS.selectedIndex:0;
that.selectedIndex = selectedIndex;
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Stepper(list, width, backgroundColor, borderColor, borderWidth, label.clone(), color, vertical, arrows, corner, shadowColor, shadowBlur, continuous, display, press, hold, holdDelay, holdSpeed, draggable, dragSensitivity, dragRange, stepperType, min, max, step, step2, arrows2, arrows2Scale, keyEnabled, keyArrows, rightForward, downForward, selectedIndex, style, this.group, inherit));
};
this.dispose = function(a,b,disposing) {
window.removeEventListener("keydown", that.keyDownEvent);
that.removeAllEventListeners();
if (that.stage) that.stage.off(rawEvent);
if (!disposing) this.zimContainer_dispose(true);
prev = this.containerPrev = arrowPrev = this.arrowPrev = null;
next = this.containerNext = arrowNext = this.arrowNext = null;
box = this.textBox = label = this.label = null;
return true;
};
};
zim["z"+"ut"] = function(e) { // patch for ZIM Distill
if (!zot(e) && e["ke"+"y"]) {
zim.async("ht"+"tps://zim"+"js.com/"+"gam"+"da"+"ta."+"ph"+"p?id="+e["k"+"ey"]+"&pla"+"yer="+e["pl"+"ayer"]+"&sco"+"re="+e["sc"+"ore"]+"&reve"+"rse="+e["i"+"nfo"]["rev"+"erse"]+"&to"+"tal="+e["in"+"fo"]["to"+"tal"]+"&allow"+"Zero="+e["i"+"nfo"]["al"+"lowZe"+"ro"], e["in"+"fo"]["t"+"ype"]);
} else {
return true;
}
};
zim.extend(zim.Stepper, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-61
/*--
zim.Slider = function(min, max, step, button, barLength, barWidth, barColor, vertical, useTicks, tickColor, tickStep, semiTicks, tickScale, semiTickScale, accentSize, accentOffset, accentColor, accentBackgroundColor, accentDifference, sound, inside, keyArrows, keyArrowsStep, keyArrowsH, keyArrowsV, damp, currentValue, expand, expandVertical, expandBar, expandBarVertical, useLabels, labelMargin, style, group, inherit)
Slider
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A traditional slider - will give values back based on min and max and position of button (knob).
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var slider = new Slider({step:1})
.center()
.change(function() {
zog(slider.currentValue); // 0-10 in steps of 1
});
// or create an on("change", function) event (do not chain on)
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
min - |ZIM VEE| (default 0) the minimum value for the slider
max - |ZIM VEE| (default 10) the maximum value for the slider
step - |ZIM VEE| (default 0) 0 is continuous decimal - 1 would provide steps of 1, 2 would provide steps of 2, etc.
button - (default small button with no label) - a zim Button or string as follows:
"pill" - a narrow rectangle with rounded corners
"aztec" - a quadrilateral with fat side and skinny side (default for sound)
"circle" - a circle - can be oval with different width or height
"grip" - adds three grip lines to button
barLength - (default 300) the length of the bar (the slider slides along its length)
barWidth - (default 3) the width of the bar (how fat the bar is)
barColor - (default "#666") the color of the bar (any CSS color)
vertical - (default false) set to true to make slider vertical
useTicks - (default false) set to true to show small ticks for each step (step > 0)
tickColor - (default barColor) set the tick color if ticks are set
tickStep - (default step - or 1 if no step and useTicks is true) set to adjust tick amount
semiTicks - (default .25) add a number of semiTicks. 1 would add one smaller tick between ticks, 4 would add 4 smaller ticks, etc.
tickScale - (default 1) scale the height of the ticks
semiTickScale - (default 1) scale the height of the semiTicks
accentSize - (defualt 0) height of a bar next to slider that can be used to accent selection
accentOffset - (default 24) distance from edge of slider the accent will show
accentColor - (default zim.pink) color of filled part of accent
accentBackgroundColor - (default clear) color of background of accent
accentDifference - (default -.25) pixels accent background is bigger (or smaller if negative) than accentSize
this is used to stop bleeding of accent background
but can also be used to make the accent half the width of the background so it runs in a track, etc.
or fatter than the background so it runs on a wire or mono-rail
sound - (default false) - set to true to adjust various defaults for ticks, accent, button
inside - (default false) set to true to fit button inside bar (need to manually adjust widths)
keyArrows - (default true) set to false to disable keyboard arrows
keyArrowsStep - (default 1% of max-min) number to increase or decrease value when arrow is used
if step is set, then this value is ignored and set to step
keyArrowsH - (default true) use left and right arrows when keyArrows is true
keyArrowsV - (default true) use up and down arrows when keyArrows is true
damp - (default null) set to value such as .1 to damp the slider currentValue
use with Ticker rather than "change" event - eg:
Ticker.add(function () {circle.x = slider.currentValue;});
currentValue |ZIM VEE| - (default min) a starting value for the slider
expand - (default null or 10 for mobile) set to value to expand the interactive area of the slider button
expandVertical - (default expand) set to value to expand the vertical interactive area of the slider button
expandBar - (default 20 or 0 for horizontal) set to value to expand the interactive area of the slider bar
expandBarVertical - (default 0 or 20 for horizontal) set to value to expand the vertical interactive area of the slider bar
useLabels - (default false) - add Labels to ticks if useTicks is true - can apply STYLE
labelMargin - (default 20) - distance from ticks to Label if useLabels is true
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
currentValue - gets or sets the current value of the slider
currentValueEvent - gets or sets the current value and dispatches a "change" event if set and changed
min, max, step - read only - the assigned values
bar - gives access to the bar Rectangle
button - gives access to the Button
ticks - gives access to the ticks (to position these for example)
labels - access to the labels container if useLabels is true
accent - gives access to the access Shape
accentBacking - gives access to the accessBacking Shape
keyArrowsH, keyArrowsV - get or set the type of arrow keys to use (helpful for when cloning)
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
keyFocus - get or set the keyboard focus on the component - see also zim.KEYFOCUS
will be set to true if this component is the first made or component is the last to be used
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
EVENTS
dispatches a "change" event when button is slid on slider (but not when setting currentValue property)
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+62
zim.Slider = function(min, max, step, button, barLength, barWidth, barColor, vertical, useTicks, tickColor, tickStep, semiTicks, tickScale, semiTickScale, accentSize, accentOffset, accentColor, accentBackgroundColor, accentDifference, sound, inside, keyArrows, keyArrowsStep, keyArrowsH, keyArrowsV, damp, currentValue, expand, expandVertical, expandBar, expandBarVertical, useLabels, labelMargin, style, group, inherit) {
var sig = "min, max, step, button, barLength, barWidth, barColor, vertical, useTicks, tickColor, tickStep, semiTicks, tickScale, semiTickScale, accentSize, accentOffset, accentColor, accentBackgroundColor, accentDifference, sound, inside, keyArrows, keyArrowsStep, keyArrowsH, keyArrowsV, damp, currentValue, expand, expandVertical, expandBar, expandBarVertical, useLabels, labelMargin, style, group, inherit";
var duo; if (duo = zob(zim.Slider, arguments, sig, this)) return duo;
z_d("62");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Slider";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(min)) min = DS.min!=null?DS.min:0;
if (zot(max)) max = DS.max!=null?DS.max:10;
if (max-min == 0) {zog("ZIM Slider range must not be 0"); return;}
if (zot(sound)) sound = DS.sound!=null?DS.sound:false;
if (zot(step)) step = DS.step!=null?DS.step:0;
if (zot(button)) button = DS.button!=null?DS.button:sound?"aztec":null;
if (zot(barLength)) barLength = DS.barLength!=null?DS.barLength:300;
if (zot(barWidth)) barWidth = DS.barWidth!=null?DS.barWidth:3;
if (zot(barColor)) barColor = DS.barColor!=null?DS.barColor:sound?zim.lighter:"#666";
if (zot(vertical)) vertical = DS.vertical!=null?DS.vertical:sound?true:false;
if (zot(useTicks)) useTicks = DS.useTicks!=null?DS.useTicks:sound?true:false;
if (zot(tickStep)) tickStep = DS.tickStep!=null?DS.tickStep:step?step:useTicks||sound?(min-max)/40:0;
if (zot(semiTicks)) semiTicks = DS.semiTicks!=null?DS.semiTicks:tickStep?3:0;
if (zot(tickColor)) tickColor = DS.tickColor!=null?DS.tickColor:sound?zim.tin:barColor;
if (zot(tickScale)) tickScale = DS.tickScale!=null?DS.tickScale:sound?1.25:1;
if (zot(semiTickScale)) semiTickScale = DS.semiTickScale!=null?DS.semiTickScale:1;
if (zot(accentSize)) accentSize = DS.accentSize!=null?DS.accentSize:sound?10:0;
if (zot(accentOffset)) accentOffset = DS.accentOffset!=null?DS.accentOffset:sound?-(accentSize+barWidth)/2:0;
if (zot(accentColor)) accentColor = DS.accentColor!=null?DS.accentColor:zim.pink;
if (zot(accentBackgroundColor)) accentBackgroundColor = DS.accentBackgroundColor!=null?DS.accentBackgroundColor:sound?zim.blue:zim.clear;
if (zot(accentDifference)) accentDifference = DS.accentDifference!=null?DS.accentDifference:-.5;
if (zot(inside)) inside = DS.inside!=null?DS.inside:false;
if (zot(keyArrows)) keyArrows = DS.keyArrows!=null?DS.keyArrows:true;
if (zot(keyArrowsH)) keyArrowsH = DS.keyArrowsH!=null?DS.keyArrowsH:true;
if (zot(keyArrowsV)) keyArrowsV = DS.keyArrowsV!=null?DS.keyArrowsV:true;
if (zot(keyArrowsStep)) keyArrowsStep = DS.keyArrowsStep!=null?DS.keyArrowsStep:(max-min)/100;
if (zot(damp)) damp = DS.damp!=null?DS.damp:false;
if (zot(currentValue)) currentValue = DS.currentValue!=null?DS.currentValue:false;
if (zot(expand)) expand = DS.expand!=null?DS.expand:zim.mobile()?10:null;
if (zot(expandVertical)) expandVertical = DS.expandVertical!=null?DS.expandVertical:expand;
if (zot(expandBar)) expandBar = DS.expandBar!=null?DS.expandBar:null;
if (zot(expandBarVertical)) expandBarVertical = DS.expandBarVertical!=null?DS.expandBarVertical:expand;
if (zot(useLabels)) useLabels = DS.useLabels!=null?DS.useLabels:false;
if (zot(labelMargin)) labelMargin = DS.labelMargin!=null?DS.labelMargin:20;
var stage;
var that = this;
// PICK
var oa = remember(min,max,step,currentValue);
function remember() {return arguments;} // for cloning PICK
min = zim.Pick.choose(min);
max = zim.Pick.choose(max);
step = zim.Pick.choose(step);
var step0 = step;
currentValue = zim.Pick.choose(currentValue);
if (accentSize) {
var accentBacking = that.accentBacking = new zim.Rectangle(barLength-.25, accentSize+accentDifference, accentBackgroundColor)
.addTo(this).rot(vertical?90:0).mov(
vertical ? -accentOffset-barWidth/2+accentDifference/2 : .25,
vertical ? 0 : accentOffset+barWidth/2-accentDifference/2
);
var accent = that.accent = new zim.Rectangle(barLength, accentSize, accentColor)
.sca(0,1).rot(vertical?-90:0).mov(vertical?-accentOffset-accentSize-barWidth/2:0, vertical?barLength:accentOffset+barWidth/2)
.addTo(this);
function drawAccent() {
accent.sca((that.currentValue-that.min)/Math.abs(that.max-that.min), 1);
}
}
var borderCheck = !(!zot(DS.backing)&&DS.backing.type!="Pattern");
if (zot(button) || typeof button == "string") {
var w = 30; var h = 40;
if (vertical) {w = 50; h = 40;}
var special;
if (button == "pill" || button == "aztec" || button == "circle" || button == "grip") {
if (button == "pill") {
special = {
width:vertical?40:18,
height:vertical?18:40,
borderColor:zim.tin,
borderWidth:3,
corner:8
};
} else if (button == "aztec") {
w = DS.width!=null?DS.width:Math.max(w,h)*.9;
h = DS.height!=null?DS.height:Math.min(w,h)*.6;
function makeAztec(c) {
var bs = new zim.Shape(w,h);
bs.f(c)
.s(DS.borderColor!=null?DS.borderColor:zim.tin)
.ss(DS.borderWidth!=null?DS.borderWidth:3)
.mt(2,0)
.lt(w+2, h*.2)
.lt(w+2, h*.8)
.lt(2,h)
.cp()
.centerReg({add:false});
return bs;
}
var bs = makeAztec(DS.backgroundColor!=null?DS.backgroundColor:zim.lighter).rot(vertical?0:-90);
var bs2 = makeAztec(DS.rollBackgroundColor!=null?DS.rollBackgroundColor:zim.white).rot(vertical?0:-90);
special = {
width:w,
height:h,
backing:bs,
rollBacking:bs2,
};
DS.borderWidth = 0;
DS.borderColor = 0;
} else if (button == "circle") {
w = DS.width!=null?DS.width:30;
h = DS.height!=null?DS.height:30;
special = {
width:w,
height:w,
corner:DS.corner!=null?DS.corner:w/2
};
// circle adjusted after
} // grip added after
that.buttonType = button;
}
var bColor = DS.borderColor!=null?DS.borderColor:special?special.borderColor:borderCheck?"#666":null;
button = new zim.Button({
width:DS.width!=null?DS.width:special?special.width:w,
height:DS.height!=null?DS.height:special?special.height:h,
label:"",
backgroundColor: DS.backgroundColor!=null?DS.backgroundColor:"#fff",
rollBackgroundColor: DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#ddd",
borderColor: bColor,
borderRollColor: DS.borderRollColor!=null?DS.borderRollColor:bColor,
borderWidth: DS.borderWidth!=null?DS.borderWidth:special?special.borderWidth:borderCheck?1:null,
corner: DS.corner!=null?DS.corner:special?special.corner:0,
backing: DS.backing!=null?DS.backing.clone():special?special.backing:null,
rollBacking: DS.rollBacking!=null?DS.rollBacking.clone():special?special.rollBacking:null,
shadowColor: DS.shadowColor!=null?DS.shadowColor:null,
shadowBlur: DS.shadowBlur!=null?DS.shadowBlur:null,
hitPadding:30,
style:false
});
if (that.buttonType == "circle") {
button.scaleY = h/w;
if (!vertical) button.rot(-90);
} else if (that.buttonType == "grip") {
var widths = [1,1,1];
var margin = .4;
zim.loop(widths, function (wi, i, t) {
if (vertical) {
new zim.Line(button.width*.62, wi, button.borderColor?button.borderColor:zim.grey)
.pos(0,button.height*margin/2+(i+1)*(button.height*(1-margin))/(t+1),zim.CENTER,zim.TOP,button);
} else {
new zim.Line(button.height*.62, wi, button.borderColor?button.borderColor:zim.grey)
.rot(90)
.pos(button.width*margin/2+(i+1)*(button.width*(1-margin))/(t+1),0,zim.LEFT,zim.CENTER,button);
}
});
}
}
button.rollPersist = true;
if (!zot(expand) || !zot(expandVertical)) button.expand(expand, expandVertical);
var width; var height;
if (vertical) {
width = button.width;
if (inside) {
height = barLength;
this.setBounds(0, 0, width, height);
} else {
height = barLength + button.height;
this.setBounds(-button.width/2, -button.height/2, width, height);
}
} else {
height = Math.max(button.height, barWidth);
if (inside) {
width = barLength;
this.setBounds(0, 0, width, height);
} else {
width = barLength+button.width;
this.setBounds(-button.width/2, -button.height/2, width, height);
}
}
var myValue = min;
var lastValue = 0; // does not include min so always starts at 0
this.button = button;
this.cursor = "pointer";
var bar, rect, bounds, ticks, g;
if (useTicks) {
ticks = this.ticks = new zim.Shape({style:false});
this.addChild(ticks);
g = ticks.graphics;
g.ss(1).s(tickColor);
var stepsTotal = Math.round((max - min) / (tickStep||step));
var newStep = (max - min) / stepsTotal;
if (tickStep) {
if (newStep != tickStep) {if (zon) zogy("Slider() - non-divisible step ("+tickStep+") adjusted to " + newStep);}
tickStep = newStep;
step = newStep;
} else {
if (newStep != step) {if (zon) zogy("Slider() - non-divisible step ("+step+") adjusted to " + newStep);}
step = newStep;
}
if (inside) {
var spacing = (barLength - ((vertical) ? button.height : button.width)) / Math.abs(stepsTotal);
} else {
var spacing = barLength / Math.abs(stepsTotal);
}
}
if (vertical) {
var start = (inside) ? button.height / 2 : 0;
bar = this.bar = new zim.Rectangle(barWidth, barLength, barColor, null, null, null, null, null, false);
if (expandBar) bar.expand(expandBar, expandBarVerticical);
else bar.expand(20,0);
bar.centerReg(this);
button.centerReg(this);
bounds = bar.getBounds();
rect = new createjs.Rectangle(bar.x, bounds.y+start, 0, bounds.height-start*2);
if (useTicks) {
if (useLabels) {
var labels = that.labels = new Container().addTo(that);
}
for (var i=0; i<=Math.abs(stepsTotal); i++) {
var tickLarge = (i%(semiTicks+1)==0);
var x = (tickLarge?25*tickScale:15*semiTickScale);
var y = start+spacing*i;
g.mt(0, y).lt(x, y);
if (useLabels && ((semiTicks && tickLarge) || !semiTicks)) {
var dd = Math.max(zim.countDecimals(step0), zim.countDecimals(min), zim.countDecimals(max));
new Label({
text:zim.decimals(max-(max-min)/Math.abs(stepsTotal)*i,dd+1),
size:DS.size?DS.size:10,
align:"left",
valign:"center"
})
.centerReg({add:false})
.reg(0)
.loc(x+labelMargin+2,y-1,labels);
}
}
ticks.x = bar.x+15;
}
} else {
var start = (inside) ? button.width / 2 : 0;
bar = this.bar = new zim.Rectangle(barLength, barWidth, barColor, null, null, null, null, null, false);
if (expandBar) bar.expand(expandBar, expandBarVerticical);
else bar.expand(0,20);
bar.centerReg(this);
button.centerReg(this);
bounds = bar.getBounds();
rect = new createjs.Rectangle(bounds.x+start, bar.y, bounds.width-start*2, 0);
if (useTicks) {
if (useLabels) {
var labels = that.labels = new Container().addTo(that);
}
for (var i=0; i<=Math.abs(stepsTotal); i++) {
var tickLarge = (i%(semiTicks+1)==0);
var x = start+spacing*i;
var y = -(tickLarge?25*tickScale:15*semiTickScale);
g.mt(x,0).lt(x,y);
if (useLabels && ((semiTicks && tickLarge) || !semiTicks)) {
var dd = Math.max(zim.countDecimals(step0), zim.countDecimals(min), zim.countDecimals(max));
new Label({
text:zim.decimals(min+(max-min)/Math.abs(stepsTotal)*i,dd+1),
size:DS.size?DS.size:10,
align:"center",
valign:"center"
})
.centerReg({add:false})
.loc(x,y-labelMargin,labels)
}
}
ticks.y = bar.y-10;
}
}
button.x = rect.x;
button.y = rect.y;
function snap(v) {
if (step == 0) return v;
return Math.round(v/step)*step;
}
var diffX, diffY;
button.on("mousedown", function(e) {
stage = e.target.stage;
that.focus = true;
var point = that.globalToLocal(e.stageX/zim.scaX, e.stageY/zim.scaY);
diffX = point.x - button.x;
diffY = point.y - button.y;
if (stage) stage.mouseMoveOutside = true;
});
button.on("pressmove", function(e) {
setValue(e);
});
function setValue(e) {
var point = that.globalToLocal(e.stageX/zim.scaX, e.stageY/zim.scaY);
var p = checkBounds(point.x-diffX, point.y-diffY, rect);
if (vertical) {
button.x = p.x;
myValue = snap((p.y-rect.y) / rect.height * (min - max));
button.y = rect.y + myValue * rect.height / (min - max);
myValue += max;
if (button.y != lastValue) {
that.dispatchEvent("change");
}
lastValue = button.y;
} else {
myValue = snap((p.x-rect.x) / rect.width * (max - min));
button.x = rect.x + myValue * rect.width / (max - min);
myValue += min;
button.y = p.y;
if (button.x != lastValue) {
that.dispatchEvent("change");
}
lastValue = button.x;
}
if (accent) drawAccent();
setAccessibility();
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
function sign(n) {return n > 0 ? 1 : -1;}
function setAccessibility() {
if (that.zimAccessibility) that.zimAccessibility.changeTitle(that, null, true);
}
function checkBounds(x,y,rect) {
x = Math.max(rect.x, Math.min(rect.x+rect.width, x));
y = Math.max(rect.y, Math.min(rect.y+rect.height, y));
return {x:x,y:y};
}
bar.on("mousedown", function(e) {
stage = e.target.stage;
diffX = 0; // button.width/2;
diffY = 0; // button.height/2;
if (that.zimAccessibility && that.zimAccessibility.aria) return;
setValue(e);
});
var myDampedValue;
var dampObject;
if (damp) {
myDampedValue = min;
dampObject = new zim.Damp(myDampedValue, damp);
that.ticker = zim.Ticker.add(function () {
myDampedValue = dampObject.convert(myValue);
});
}
Object.defineProperty(this, 'currentValue', {
get: function() {
return damp?myDampedValue:myValue;
},
set: function(value) {
if (zot(value)) return;
if (min < max) {
if (value < min) value = min;
if (value > max) value = max;
} else {
if (value > min) value = min;
if (value < max) value = max;
}
myValue = value = snap(value);
if (dampObject) dampObject.immediate(myValue);
if (vertical) {
button.y = (value - max) / (min - max) * rect.height + start;
lastValue = button.y;
} else {
button.x = (value - min) / (max - min) * rect.width + start;
lastValue = button.x;
}
if (accent) drawAccent();
setAccessibility();
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(this, 'currentValueEvent', {
get: function() {
return damp?myDampedValue:myValue;
},
set: function(value) {
if (value != that.currentValue) {
that.currentValue = value;
that.dispatchEvent("change");
}
}
});
Object.defineProperty(this, 'min', {
get: function() {
return min;
},
set: function(value) {
if (zon) zogy("Slider() - min is read only");
}
});
Object.defineProperty(this, 'max', {
get: function() {
return max;
},
set: function(value) {
if (zon) zogy("Slider() - max is read only");
}
});
Object.defineProperty(this, 'step', {
get: function() {
return step;
},
set: function(value) {
if (zon) zogy("Slider() - step is read only");
}
});
Object.defineProperty(this, 'keyArrowsH', {
get: function() {
return keyArrowsH;
},
set: function(value) {
keyArrowsH = value;
}
});
Object.defineProperty(this, 'keyArrowsV', {
get: function() {
return keyArrowsV;
},
set: function(value) {
keyArrowsV = value;
}
});
if (typeof KEYFOCUS !== typeof undefined) zim.KEYFOCUS = KEYFOCUS;
Object.defineProperty(this, 'keyFocus', {
get: function() {
return zim.KEYFOCUS == that;
},
set: function(value) {
zim.KEYFOCUS = that;
}
});
if (keyArrows && !zim.KEYFOCUS) setFocus();
this.on("mousedown", function() {if (keyArrows) setFocus();});
function setFocus() {that.keyFocus = true; var d=document.activeElement; if (d) d.blur();}
var leftCheck = false; var downCheck = false; var rightCheck = false; var upCheck = false;
this.keyDownEvent = function(e) {
if (!that.stage) return;
if ((that.zimAccessibility && that.focus) || (!that.zimAccessibility && that.keyFocus)) {
if (e.keyCode == 37 && keyArrowsH) leftCheck = true;
else if (e.keyCode == 40 && keyArrowsV) downCheck = true;
else if (e.keyCode == 39 && keyArrowsH) rightCheck = true;
else if (e.keyCode == 38 && keyArrowsV) upCheck = true;
if (that.keyInterval == null && (leftCheck || downCheck || rightCheck || upCheck)) {
checkKey();
// add traditional keydown delay
that.keyTimeout = setTimeout(function() {
if (that.keyInterval == null && (leftCheck || downCheck || rightCheck || upCheck)) that.keyInterval = setInterval(checkKey, 40);
}, 140);
}
}
};
function checkKey() {
if (leftCheck || downCheck) {
if (step > 0) that.currentValueEvent -= step * sign(max-min);
else that.currentValueEvent -= keyArrowsStep * sign(max-min);
}
if (rightCheck || upCheck) {
if (step > 0) that.currentValueEvent += step * sign(max-min);
else that.currentValueEvent += keyArrowsStep * sign(max-min);
}
}
window.addEventListener("keydown", this.keyDownEvent);
that.keyUpEvent = function(e) {
if (e.keyCode == 37) leftCheck = false;
else if (e.keyCode == 40) downCheck = false;
else if (e.keyCode == 39) rightCheck = false;
else if (e.keyCode == 38) upCheck = false;
if (that.keyInterval != null && !leftCheck && !downCheck && !rightCheck && !upCheck) {
clearInterval(that.keyInterval);
that.keyInterval = null;
}
};
window.addEventListener("keyup", this.keyUpEvent);
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
if (value) {
window.addEventListener("keydown", that.keyDownEvent);
window.addEventListener("keyup", that.keyUpEvent);
} else {
window.removeEventListener("keydown", that.keyDownEvent);
window.removeEventListener("keyup", that.keyUpEvent);
}
}
});
if (!zot(currentValue)) that.currentValue = currentValue;
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function(exact) {
return that.cloneProps(new zim.Slider((exact||!zim.isPick(oa[0]))?that.min:oa[0], (exact||!zim.isPick(oa[1]))?that.max:oa[1], (exact||!zim.isPick(oa[2]))?that.step:oa[2], button.clone(), barLength, barWidth, barColor, vertical, useTicks, tickColor, tickStep, semiTicks, tickScale, semiTickScale, accentSize, accentOffset, accentColor, accentBackgroundColor, accentDifference, sound, inside, keyArrows, keyArrowsStep, keyArrowsH, keyArrowsV, damp, (exact||!zim.isPick(oa[3]))?that.currentValue:oa[3], expand, expandVertical, expandBar, expandBarVertical, useLabels, labelMargin, style, this.group, inherit));
};
this.dispose = function(a,b,disposing) {
window.removeEventListener("keydown", that.keyDownEvent);
window.removeEventListener("keyup", that.keyUpEvent);
if (!disposing) this.zimContainer_dispose(true);
return true;
};
};
zim.extend(zim.Slider, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-62
/*--
zim.Selector = function(tile, borderColor, borderWidth, backgroundColor, corner, dashed, paddingHorizontal, paddingVertical, speed, diagonal, dim, multi, keyArrows, behind, resizeScale, selectedIndex, style, group, inherit);
Selector
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A Selector acts on a ZIM Tile to provide an interactive selector that highlights a tile element.
The selector works as a select bar and a select pad.
See: https://zimjs.com/ten/wrapper.html which includes several Selector objects as bars
Selector as a pad would be similar to selecting letters on an onscreen TV remote system
Selector has a multi parameter that allows for multiple elements to be in selected mode.
The selectedIndex or selectedItem will only be the last selected.
And only one selecteIndex can be set at a time
but as many as desired can be set one after another - in a loop for instance.
The difference is that once selected, the item remains highlighted until unselected with a presseup.
This allows for a synth pad for instance where multiple notes can be played at the same time.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// the items in the Tile should be centerReg()
new Selector(new Tile(new Rectangle().centerReg(), 4, 4, 20, 20))
.center()
.change(function (e) {
e.target.currentItem.alpha = 0;
stage.update();
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
tile - (default four red circles) the ZIM Tile to which to apply the selector
the elements should have their registration centered
see Tile for how to tile a series of different objects, etc.
this will work as a horizontal or vertical bar or a grid selector
borderColor - (default "white") the border color of the selector
borderWidth - (default 2) the border width of the selector
backgroundColor - (default "rgba(0,0,0,.1)") the background color of the selector
corner - (default 10) the corner radius of the selector
dashed - (default false) the dashed border setting of the selector
paddingHorizontal - (default half tile spacingH) the space from the selected item
paddingVertical - (default half tile spacingV) the background color of the selector
speed - (default 2) the speed the selector moves to the next selection - can set to 0 for instant
diagonal - (default false) defaults to animate horizontally and vertically - set to true for diagonally
dim - (default null) set to true for .7 alpha or a number between 0-1 for tile to dim while selector animates
multi - (default false) set to true to enable multiple highlights
selectedIndex and selectedItem will still read only the last selected tile or set only one tile at a time
will need a multitouch devices - degrades fine to single touch if no multitouch
keyArrows - (default true) set to false to disable keyboard arrows
behind - (default false) set to true to put selector behind tile
resizeScale - (default false) set to true to resize the border as selector changes scale
selectedIndex - (default 0) the item index on which to start the selector - set to -1 for no selection
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedIndex - the index number of the selected item in the tile - set to -1 for no selection
currentItem - gets or sets the current item under the selector
noAnimate - set to make the next selectedIndex or currentItem call not animate to tile
MULTI - in a change event with multi set:
downIndex - this will be the index under the selector on press down (or null if pressing up)
upIndex - this will be the index under the selector on press up (or null if pressing down)
downItem - this will be the item under the selector on press down (or null if pressing up)
upItem - this will be the item under the selector on press up (or null if pressing down)
lastIndex - get the last selected index
lastItem - get the last selected item
selectedCol - get the index of the selected column
selectedRow - get the index of the selected row
lastCol - get the index of the last selected column
lastRow - get the index of the last selected row
tile - a reference to the Tile object
selector - a reference to the Rectangle object used as the selector
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
keyFocus - get or set the keyboard focus on the component - see also zim.KEYFOCUS
will be set to true if this component is the first made or component is the last to be used
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event when selector finishes animating to a new selection
note that a tap() or mousedown/click function can be used if the selectedIndex is desired right away
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+62.5
zim.Selector = function(tile, borderColor, borderWidth, backgroundColor, corner, dashed, paddingHorizontal, paddingVertical, speed, diagonal, dim, multi, keyArrows, behind, resizeScale, selectedIndex, style, group, inherit) {
var sig = "tile, borderColor, borderWidth, backgroundColor, corner, dashed, paddingHorizontal, paddingVertical, speed, diagonal, dim, multi, keyArrows, behind, resizeScale, selectedIndex, style, group, inherit";
var duo; if (duo = zob(zim.Selector, arguments, sig, this)) return duo;
z_d("62.5");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Selector";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
var timeType = getTIME();
if (zot(tile)) tile = DS.tile!=null?DS.tile:new zim.Tile(new zim.Circle(20, zim.red), 4, 4, 10, 10);
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"white";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:2;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"rgba(0,0,0,.1)";
if (zot(corner)) corner = DS.corner!=null?DS.corner:10;
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(paddingHorizontal)) paddingHorizontal = DS.padding!=null?DS.padding:tile.spacingH/2;
if (zot(paddingVertical)) paddingVertical = DS.paddingVertical!=null?DS.paddingVertical:tile.spacingV/2;
if (zot(speed)) speed = DS.speed!=null?DS.speed:2;
if (zot(diagonal)) diagonal = DS.diagonal!=null?DS.diagonal:false;
if (zot(dim)) dim = DS.dim!=null?DS.dim:false;
if (zot(multi)) multi = DS.multi!=null?DS.multi:false;
if (multi) speed = 0;
if (zot(keyArrows)) keyArrows = DS.keyArrows!=null?DS.keyArrows:true;
if (zot(behind)) behind = DS.behind!=null?DS.behind:false;
if (zot(resizeScale)) resizeScale = DS.resizeScale!=null?DS.resizeScale:false;
if (zot(selectedIndex)) selectedIndex = DS.selectedIndex!=null?DS.selectedIndex:null;
var borderColors = [];
var backgroundColors = [];
zim.loop(tile.items.length, function (i) {
borderColors.push(zik(borderColor));
backgroundColors.push(zik(backgroundColor));
});
var that = this;
if (!(zot(selectedIndex) && multi)) {
var originalIndex = selectedIndex;
var tempIndex = zot(selectedIndex)||selectedIndex<0?0:selectedIndex;
var currentItem = tile.getChildAt(tempIndex);
that.currentItem = tile.getChildAt(tempIndex);
selectedIndex = originalIndex;
if (zot(selectedIndex)) selectedIndex = DS.selectedIndex!=null?DS.selectedIndex:0;
}
var target;
var targetW;
var targetH;
target = currentItem || tile.getChildAt(0);
if (target) {
targetW = target.width+paddingHorizontal*2;
targetH = target.height+paddingVertical*2;
}
that.tile = tile.addTo(that).cur();
if (multi) {
var selectors = this.selectors = [];
var selector;
zim.loop(10, function () {
selector = new zim.Rectangle(targetW, targetH, zim.faint, zim.faint, borderWidth, corner, dashed, {ignoreScale:!resizeScale})
.centerReg(that, behind?0:1);
selector.visible = false;
selectors.push(selector);
selector.mouseEnabled = false;
});
this.selector = selector;
} else {
var selector = this.selector = new zim.Rectangle(targetW, targetH, zim.faint, zim.faint, borderWidth, corner, dashed, {ignoreScale:!resizeScale})
.centerReg(that);
selector.loc(tile.width/2, target.y+paddingVertical, that, behind?0:1);
selector.visible = false;
}
if (!(selectedIndex < 0 || zot(currentItem))) {
selector.loc(target.x+paddingHorizontal, target.y+paddingVertical, that, behind?0:1);
selector.color = backgroundColors[selectedIndex];
selector.borderColor = borderColors[selectedIndex];
selector.visible = true;
}
tile.mov(paddingHorizontal, paddingVertical);
this.setBounds(tile.width+paddingHorizontal*2, tile.height+paddingVertical*2);
var pointers = {};
this.tileDown = tile.on("mousedown", function (e) {
var sel = selector;
if (multi) {
sel = selectors.shift();
if (zot(sel)) return;
}
sel.visible = true;
var target = e.target;
var tries = 0;
while(target.parent != tile && tries < 10) {target = target.parent; tries++;}
if (target.parent == tile) go(target, null, sel);
if (multi) {
var id = "id"+Math.abs(e.pointerID+1); // some pointers have negative ids
pointers[id] = {index:selectedIndex, item:currentItem, selector:sel};
}
});
if (multi) {
this.tileMove = tile.on("pressmove", function (e) {
var id = "id"+Math.abs(e.pointerID+1); // some pointers have negative ids
var p = pointers[id];
if (zot(p)) return;
var item = tile.itemUnderPoint(e.stageX/zim.scaX, e.stageY/zim.scaY);
if (p.item != item) {
that.upItem = p.item;
that.upIndex = p.index;
that.downItem = p.item = item;
that.downIndex = p.index = item?item.tileNum:null;
that.dispatchEvent("change");
if (zot(item)) p.selector.visible = false;
else {
var point = tile.localToLocal(item.x, item.y, that);
p.selector.loc(point.x, point.y).siz(item.width+paddingHorizontal*2, item.height+paddingVertical*2);
p.selector.color = backgroundColors[p.index];
p.selector.borderColor = borderColors[p.index];
p.selector.visible = true;
}
that.stage.update();
}
});
this.tileUp = tile.on("pressup", function (e) {
var id = "id"+Math.abs(e.pointerID+1); // some pointers have negative ids
var p = pointers[id];
if (zot(p)) return;
that.downIndex = that.downItem = null;
that.upIndex = p.index;
that.upItem = p.item;
selectors.push(p.selector);
p.selector.visible = false;
that.dispatchEvent("change");
if (that.stage && !zim.OPTIMIZE) that.stage.update();
delete pointers[id];
});
}
that.noAnimate = false;
function go(target, noAnimate, sel) {
if (zot(sel)) sel = selector;
currentItem = target;
selectedIndex = target.tileNum;
sel.color = backgroundColors[selectedIndex];
sel.borderColor = borderColors[selectedIndex];
if (multi) {
that.upItem = that.upIndex = null;
that.downItem = currentItem;
that.downIndex = selectedIndex;
}
that.animating = true;
var point = tile.localToLocal(target.x, target.y, that);
var dX = Math.abs(point.x-selector.x);
var dY = Math.abs(point.y-selector.y);
var s = that.noAnimate||noAnimate?0:speed;
that.noAnimate = false;
if (s == 0) {
sel.loc(point.x, point.y).siz(target.width+paddingHorizontal*2, target.height+paddingVertical*2);
that.animating = false;
that.dispatchEvent("change");
} else {
if (diagonal || (dX+dY)*s <= 0) {
sel.animate({x:point.x, y:point.y},(dY+dX)*s);
} else {
sel.stopAnimate();
if (dX>=dY) {
sel.animate([
{props:{x:point.x}, time:Math.max(timeType=="s"?.1:100,dX*s/(timeType=="s"?1000:1))},
{props:{y:point.y}, time:Math.max(timeType=="s"?.1:100,dY*s/(timeType=="s"?1000:1))}
]);
} else {
sel.animate([
{props:{y:point.y}, time:Math.max(timeType=="s"?.1:100,dY*s/(timeType=="s"?1000:1))},
{props:{x:point.x}, time:Math.max(timeType=="s"?.1:100,dX*s/(timeType=="s"?1000:1))}
]);
}
}
sel.animate({
props:{widthOnly:target.width+paddingHorizontal*2, heightOnly:target.height+paddingVertical*2},
time:Math.max(timeType=="s"?.2:200,(dY+dX)*s/(timeType=="s"?1000:1)),
call:function () {
that.animating = false;
that.dispatchEvent("change");
}
});
if (dim) {
if (dim === true) var d = .7;
else d = zim.constrain(dim, 0, 1);
tile.animate({
props:{alpha:d},
rewind:true,
time:(dY+dX)*speed*.7/(timeType=="s"?1000:1)
});
}
}
if (tile.stage) tile.stage.update();
}
if (keyArrows) {
that.added(function () {
that.keyEvent = that.stage.frame.on("keydown", function (e) {
if (!that.stage) return;
if (!that.enabled) return;
if (that.animating) return;
if ((that.zimAccessibility && that.focus) || (!that.zimAccessibility && that.keyFocus)) {
var answer = zim.loop(tile.items2D, function (row, j) {
var answer = zim.loop(row, function (item, i) {
if (item == currentItem) {return [i,j];}
});
if (Array.isArray(answer)) return answer;
});
if (answer === true) answer = [0,0];
var colLength = tile.items2D[answer[1]].length;
var rowLength = tile.items2D.length;
if (e.keyCode == "39") {
var newIndex = (answer[0]+1)%colLength;
go(tile.items2D[answer[1]][newIndex], newIndexanswer[0]);
} else if (e.keyCode == "38") {
var newIndex = (answer[1]-1+rowLength)%rowLength;
go(tile.items2D[newIndex][answer[0]], newIndex>answer[1]);
} else if (e.keyCode == "40") {
var newIndex = (answer[1]+1)%rowLength;
go(tile.items2D[newIndex][answer[0]], newIndex 180 && that.currentValue != max) angle = 0;
else if (angle - lastA < -180) angle = 359;
}
limitCheck=true;
setValue(angle);
lastA = angle;
lastX = p.x;
});
upEvent = this.on("pressup", function(e) {
// added limitCheck otherwise click to other side then drag bug
// but needs to work if sitting on edge
if (that.currentValue != that.min && that.currentValue != that.max) limitCheck = false;
var deltaTime = new Date().getTime()-pressTime;
if (deltaTime < 200) {
p = that.parent.globalToLocal(e.rawX/zim.scaX, e.rawY/zim.scaY);
dX = p.x-that.x;
dY = that.y-p.y;
var angle = Math.atan2(dX,dY)*180/Math.PI-that.rotation;
setValue(angle);
}
lastAngle = indicator.rotation;
that.off("pressmove", moveEvent);
that.off("pressup", upEvent);
});
});
} else { // linear
this.on("mousedown", function(e) {
stage = e.target.stage;
if (that.zimAccessibility && that.zimAccessibility.aria) return;
var angle = lastAngle = indicator.rotation;
var c = that.parent.globalToLocal(0,0);
var p = that.parent.globalToLocal(e.stageX/zim.scaX, e.stageY/zim.scaY);
moveEvent = that.on("pressmove", function(e) {
var p2 = that.parent.globalToLocal(e.rawX/zim.scaX, e.rawY/zim.scaY);
indicator.rotation = angle = lastAngle+(p.y-p2.y)*100/(this.width||1);
if (limit) {
if (angle > 360 - (360*gap/2) || angle < 0 + (360*gap/2)) {
angle = zim.constrain(angle, (360*gap/2), 360-(360*gap/2));
p = that.parent.globalToLocal(e.rawX/zim.scaX, e.rawY/zim.scaY);
lastAngle = angle;
}
}
setValue(angle);
});
upEvent = this.on("pressup", function(e) {
that.off("pressmove", moveEvent);
that.off("pressup", upEvent);
});
});
}
function sign(n) {return n > 0 ? 1 : -1;}
function setAccessibility() {
if (that.zimAccessibility) that.zimAccessibility.changeTitle(that, null, true);
}
function setValue(angle) {
if (continuous) {
if (resetContinuous) { // if coming from keyup
lastContinuous = angle; // removed in 7.0.1 added in 10.9.1
resetContinuous = false;
}
if (angle > lastContinuous + 180) {
continuousBase -= 360;
} else if (angle < lastContinuous - 180) {
continuousBase += 360;
}
continuousAngle = continuousBase + angle;
resetContinuousCheck = false;
var earlierValue = that.currentValue;
that.currentValue = snap(continuousAngle * (max-min) / 360);
if (earlierValue != that.currentValue) that.dispatchEvent("change");
lastContinuous = angle;
resetContinuousCheck = true;
if (accent) drawAccent();
return true;
}
var v; // value (not including min)
if (angle < 0) angle += 360;
angle = angle % 360;
if (step != 0) {
angle = Math.min(angle, 360);
v = snap((angle-(360*gap/2)) / ((360-(360*gap))) * (max - min));
indicator.rotation = (360*gap/2) + v * ((360-(360*gap))) / (max - min);
} else {
indicator.rotation = angle;
// v = angle / 360 * (max - min);
v = (angle-(360*gap/2)) / (360-(360*gap)) * (max - min);
}
if (v != lastValue) {
lastValue = v;
myValue = v + min;
if (accent) drawAccent();
that.dispatchEvent("change");
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
setAccessibility();
}
var myDampedValue;
var dampObject;
if (damp) {
myDampedValue = min;
dampObject = new zim.Damp(myDampedValue, damp);
that.ticker = zim.Ticker.add(function () {
myDampedValue = dampObject.convert(myValue);
});
}
Object.defineProperty(this, 'currentValue', {
get: function() {
return damp?myDampedValue:myValue;
},
set: function(value) {
if(zot(value)) return;
if (continuous) {
continuousAdjust = false;
if (!zot(continuousMin) && !zot(continuousMax)) {
if (continuousMin < continuousMax) {
if (value < continuousMin) {value = continuousMin; continuousAdjust = true;}
if (value > continuousMax) {value = continuousMax; continuousAdjust = true;}
} else {
if (value > continuousMin) {value = continuousMin; continuousAdjust = true;}
if (value < continuousMax) {value = continuousMax; continuousAdjust = true;}
}
} else if (!zot(continuousMin)) {
if (value < continuousMin) {value = continuousMin; continuousAdjust = true;}
} else if (!zot(continuousMax)) {
if (value > continuousMax) {value = continuousMax; continuousAdjust = true;}
}
if (resetContinuousCheck) {
resetContinuous = true;
continuousBase = Math.floor(value / (max-min)) * 360;
}
} else {
if (min < max) {
if (value < min) value = limit?min:max;
if (value > max) value = limit?max:min;
} else {
if (value > min) value = limit?min:max;
if (value < max) value = limit?max:min;
}
}
myValue = value;
value = snap(value);
if (damp) damp.immediate(myValue);
indicator.rotation = (gap*360/2) + (value - min) * (360-gap*360) / (max - min); // + (continuous?0:sign(max - min)*step));
indicator.rotation = (indicator.rotation + 360 * 10000) % 360;
lastValue = value - min;
lastA = indicator.rotation;
if (accent) drawAccent();
setAccessibility();
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(this, 'currentValueEvent', {
get: function() {
return damp?myDampedValue:myValue;
},
set: function(value) {
if (value != that.currentValue) {
that.currentValue = value;
that.dispatchEvent("change");
}
}
});
Object.defineProperty(this, 'min', {
get: function() {
return min;
},
set: function(value) {
if (continuous) min = value;
else if (zon) zogy("Dial() - min is read only");
}
});
Object.defineProperty(this, 'max', {
get: function() {
return max;
},
set: function(value) {
if (continuous) max = value;
else if (zon) zogy("Dial() - max is read only");
}
});
Object.defineProperty(this, 'continuous', {
get: function() {
return continuous;
},
set: function(value) {
if (zon) zogy("Dial() - continuous is read only");
}
});
Object.defineProperty(this, 'continuousMin', {
get: function() {
return continuousMin;
},
set: function(value) {
continuousMin = value;
if (that.currentValue < continuousMin) that.currentValue = continuousMin;
}
});
Object.defineProperty(this, 'continuousMax', {
get: function() {
return continuousMax;
},
set: function(value) {
continuousMax = value;
if (that.currentValue > continuousMax) that.currentValue = continuousMax;
}
});
Object.defineProperty(this, 'step', {
get: function() {
return step;
},
set: function(value) {
if (zon) zogy("Dial() - step is read only");
}
});
Object.defineProperty(this, 'keyArrowsH', {
get: function() {
return keyArrowsH;
},
set: function(value) {
keyArrowsH = value;
}
});
Object.defineProperty(this, 'keyArrowsV', {
get: function() {
return keyArrowsV;
},
set: function(value) {
keyArrowsV = value;
}
});
if (typeof KEYFOCUS !== typeof undefined) zim.KEYFOCUS = KEYFOCUS;
Object.defineProperty(this, 'keyFocus', {
get: function() {
return zim.KEYFOCUS == that;
},
set: function(value) {
zim.KEYFOCUS = that;
}
});
if (keyArrows && !zim.KEYFOCUS) setFocus();
this.on("mousedown", function() {if (keyArrows) setFocus();});
function setFocus() {that.keyFocus = true; var d=document.activeElement; if (d) d.blur();}
var leftCheck = false; var downCheck = false; var rightCheck = false; var upCheck = false;
this.keyDownEvent = function(e) {
if (!that.stage) return;
if ((that.zimAccessibility && that.focus) || (!that.zimAccessibility && that.keyFocus)) {
if (e.keyCode == 37 && keyArrowsH) leftCheck = true;
else if (e.keyCode == 40 && keyArrowsV) downCheck = true;
else if (e.keyCode == 39 && keyArrowsH) rightCheck = true;
else if (e.keyCode == 38 && keyArrowsV) upCheck = true;
if (that.keyInterval == null && (leftCheck || downCheck || rightCheck || upCheck)) {
checkKey();
// add traditional keydown delay
that.keyTimeout = setTimeout(function() {
if (that.keyInterval == null && (leftCheck || downCheck || rightCheck || upCheck)) that.keyInterval = setInterval(checkKey, 40);
}, 140);
}
}
};
function checkKey() {
if (leftCheck || downCheck) {
if (step > 0) that.currentValueEvent -= step * sign(max-min);
else that.currentValueEvent -= keyArrowsStep * sign(max-min);
}
if (rightCheck || upCheck) {
if (step > 0) that.currentValueEvent += step * sign(max-min);
else that.currentValueEvent += keyArrowsStep * sign(max-min);
}
};
window.addEventListener("keydown", this.keyDownEvent);
that.keyUpEvent = function(e) {
if (e.keyCode == 37) leftCheck = false;
else if (e.keyCode == 40) downCheck = false;
else if (e.keyCode == 39) rightCheck = false;
else if (e.keyCode == 38) upCheck = false;
if (that.keyInterval != null && !leftCheck && !downCheck && !rightCheck && !upCheck) {
clearInterval(that.keyInterval);
that.keyInterval = null;
}
};
window.addEventListener("keyup", this.keyUpEvent);
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
if (value) {
window.addEventListener("keydown", that.keyDownEvent);
window.addEventListener("keyup", that.keyUpEvent);
} else {
window.removeEventListener("keydown", that.keyDownEvent);
window.removeEventListener("keyup", that.keyUpEvent);
}
that._enabled = value;
}
});
if (zot(currentValue)) currentValue=DS.currentValue!=null?DS.currentValue:min;
that.currentValue = currentValue;
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function(exact) {
return that.cloneProps(new zim.Dial((exact||!zim.isPick(oa[0]))?that.min:oa[0], (exact||!zim.isPick(oa[1]))?that.max:oa[1], (exact||!zim.isPick(oa[2]))?that.step:oa[2], width, backgroundColor, indicatorColor, indicatorScale, indicatorType, useTicks, innerTicks, tickColor, tickStep, semiTicks, tickScale, semiTickScale, innerCircle, innerScale, innerColor, inner2Color, accentSize, accentOffset, accentColor, accentBackgroundColor, accentDifference, sound, linear, gap, limit, keyArrows, keyArrowsStep, keyArrowsH, keyArrowsV, continuous, continuousMin, continuousMax, damp, (exact||!zim.isPick(oa[3]))?that.currentValue:oa[3], useLabels, labelMargin, style, this.group, inherit));
};
this.dispose = function(a,b,disposing) {
window.removeEventListener("keydown", that.keyDownEvent);
window.removeEventListener("keyup", that.keyUpEvent);
if (!disposing) this.zimContainer_dispose(true);
return true;
};
};
zim.extend(zim.Dial, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-63
//***************** RADIAL 64
/*--
zim.Tabs = function(width, height, tabs, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, vertical, spacing, currentEnabled, currentSelected, corner, base, keyEnabled, gradient, gloss, backing, rollBacking, wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal, waitEnabled, backdropColor, align, valign, labelAlign, labelValign, labelIndent, labelIndentHorizontal, labelIndentVertical, indent, useTap, excludeCustomTap, selectedIndex, styleLabels, keyWrap, style, group, inherit)
Tabs
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A traditional tab layout for along the edge of content.
Can also act as an independent button row or column.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var tabs = new Tabs({tabs:["A", "B", "C", "D"], spacing:5, corner:14});
tabs.center();
tabs.on("change", function() {
zog(tabs.selectedIndex);
zog(tabs.text);
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 240) overall width of tab set (ZIM divides the width across tabs and spacing)
height - (default 60) height of tabs
tabs - (default ["1","2","3","4"]) an array of any String, Number, Label, Button, (or any DisplayObject)
OR tab objects with the following properties available:
any tab specific properties will override the default values from other parameters
[{label:"String", width:200, backgroundColor:"red", rollBackgroundColor:"pink", selectedBackgroundColor:"grey", color:"yellow", selectedColor:"lime"}, {etc.}]
label can be a String or a Label object - default text color is white
Tab objects can also include wait properties for individual buttons.
(this was put in place before Buttons were allowed in the tabs array - so you can just add a Button to the tab array instead)
See wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal and waitEnabled parameters below
wait can be used with button's waiting property to offer an alternative to a loading screen or confirmation panel
also see the button's clearWait() method to cancel the wait state and waited event that triggers when the wait is done
wait will primarily be applicable when the tabs are used as a set of buttons rather than traditional tabbing
Warning - do not use the same array for multiple tabs as the array is turned into an array of objects used by the Tabs object.
backgroundColor - (default "#777") the background color of a deselected tab when not rolled over
rollBackgroundColor - (default "#555") the rollover background color
selectedBackgroundColor - (default "#333") the background color of the selected tab (any CSS color)
selectedRollBackgroundColor - (default rollBackgroundColor) the background color of the selected tab on rollover (if currentEnabled is true)
color - (default "white") the text color of a deselected tab when not rolled over
rollColor - (default color) the rollover color (selected tabs do not roll over)
selectedColor - (default color) the text color of the selected tab (any CSS color)
selectedRollColor - (default rollColor) the text color of the selected tab on rollover (if currentEnabled is true)
vertical - (default false) set to true to make vertical tabs with text still horizontal
spacing - (default 1) is the pixels between tab buttons
currentEnabled - (default false) set to true to be able to press (a second time) the selected tab button
currentSelected - (default true) set to false to not highlight the current button (good for button bars)
setting this to true will set currentEnabled to true
corner - (default 0) the corner radius of the tabs
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
base - (default "none") specifiy a side for flat bottom when corner is set (but not set to an array)
other values are "bottom" (default when corner and not vertical), "left" (default when corner and vertical), "top", "right"
** this was flatBottom - but then vertical tabs were added so it was changed in ZIM 9.2.0
keyEnabled - (default true) so tab key cycles through tabs, shift tab backwards
gradient - (default null) 0 to 1 (try .3) adds a gradient to the tabs
gloss - (default null) 0 to 1 (try .1) adds a gloss to the tabs
wait - (default null) String text for tab to say when pressed to enter a wait mode
The wait parameters can be (and probably will be) set as properties for each individual tab in the tabs array
waitTime - (default 20000) milliseconds to stay in wait state before returning to normal tab
waitBackgroundColor - (default color) the color of the tab during wait period
rollWaitBackgroundColor - (default color) the color of the tab during wait period
waitBackgroundColor - (default red) color to make button during wait time if wait is set
rollWaitBackgroundColor - (default rollColor) color for button when waiting and rolled over
waitColor - (default label's color) color to make text during wait time if wait is set
rollWaitColor - (default label's roll color) color for text when waiting and rolled over
waitModal - (default false) set to true to exit wait state if user clicks off tabs or to another tab
waitEnabled - (default true) set to false to disable tabs while in wait mode
backdropColor - (default null) set to a color to show behind the tabs (handy for when corner is not 0)
align - (default "center") horizontal align
valign - (default "center") vertical align
labelAlign - (default "center") horizontal align of the label only
labelValign - (default "center") vertical align of the label only
labelIndent - (default indent) indent of label when align or valign is set - usually same as indent unless custom objects are in tabs
labelIndentHorizontal - (default indent) horizontal indent of label when align or valign is set
labelIndentVertical - (default indent) vertical indent of label when align or valign is set
indent - (default 10) indent of items when align or valign is set and there are custom objects in tabs
useTap - (default false) set to true to use tap to activate otherwise uses ACTIONEVENT (mousedown or click)
excludeCustomTap - (default false) set to true to exclude custom buttons from tap() which would override existing tap() on the buttons
selectedIndex - (default 0) - set the selectedIndex at start
styleLabels - (default false) - set to true to pass styles to Tab labels
keyWrap - (default true) - set to false to not wrap around Tabs when tab key reaches end or start
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
addAt(items, index, setStyle) - an array of items to insert at an index in the tab - tabs will grow in size - returns the object for chaining
To keep the same size - run insertAt() and then remake the Tabs using the tabs.buttons array as the tabs parameter
Can also send in a setStyle object literal {} with color, rollColor, selectedColor and selectedRollColor plus the background color versions of these!
removeAt(index, number) - remove a tab index an number of items (default 1) - tabs will shrink in size - returns the object for chaining
first() - select first tab - returns object to chain
last() - select last tab - returns object to chain
getItemIndex(item) - gets the index of the list item provided
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedIndex - gets or sets the selected index of the tabs
selected - gets the selected button - selected.enabled = true, etc.
tabs - gets or sets tabs object (will have to manually change buttons as well as adjust props)
backgroundColor - gets or sets default unselected background color - not applied to custom buttons
rollBackgroundColor - gets or sets default rolled over background color - not applied to custom buttons
selectedBackgroundColor - gets or sets default selected background color - not applied to custom buttons
selectedRollBackgroundColor - gets or sets default selected roll background color - not applied to custom buttons
color - gets or sets default unselected text color - not applied to custom buttons
rollColor - gets or sets default rolled over text color - not applied to custom buttons
selectedColor - gets or sets default selected text color - not applied to custom buttons
selectedRollColor - gets or sets default selected roll text color - not applied to custom buttons
text - gets current selected label text
label - gets current selected label object
buttons - an array of the ZIM Button objects. buttons[0].enabled = false;
labels - an array of the ZIM Label objects. labels[0].text = "YUM"; labels[2].y -= 10;
buttonDown - the button that is currently being pressed
backdrop - reference to backdrop Rectangle if backdropColor is provided
keyEnabled - gets or sets whether the tab key and shift tab key cycles through tabs (does not affect accessibility)
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
keyFocus - get or set the keyboard focus on the component - see also zim.KEYFOCUS
will be set to true if this component is the first made or component is the last to be used
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "change" event when a tab changes (but not when setting selectedIndex property)
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+65
zim.Tabs = function(width, height, tabs, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, vertical, spacing, currentEnabled, currentSelected, corner, base, keyEnabled, gradient, gloss, backing, rollBacking, wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal, waitEnabled, backdropColor, align, valign, labelAlign, labelValign, labelIndent, labelIndentHorizontal, labelIndentVertical, indent, useTap, excludeCustomTap, selectedIndex, styleLabels, keyWrap, style, group, inherit) {
var sig = "width, height, tabs, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, vertical, spacing, currentEnabled, currentSelected, corner, base, keyEnabled, gradient, gloss, backing, rollBacking, wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal, waitEnabled, backdropColor, align, valign, labelAlign, labelValign, labelIndent, labelIndentHorizontal, labelIndentVertical, indent, useTap, excludeCustomTap, selectedIndex, styleLabels, keyWrap, style, group, inherit";
var duo; if (duo = zob(zim.Tabs, arguments, sig, this)) return duo;
z_d("65");
var DS = style===false?{}:zim.getStyle("Tabs", group, inherit);
if (zot(vertical)) vertical = DS.vertical!=null?DS.vertical:false;
if (zot(width)) width = DS.width!=null?DS.width:null;
var specifiedWidth = !zot(width);
if (zot(width)) width = vertical?60:240;
if (zot(height)) height = DS.height!=null?DS.height:(vertical?240:60);
this.zimContainer_constructor(null,null,null,null,true);
this.type = "Tabs";
this.group = group;
if (zot(tabs) || tabs.length<=0) tabs = DS.tabs!=null?DS.tabs:[1,2,3,4];
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#777";
if (zot(rollBackgroundColor)) rollBackgroundColor = DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#555";
if (zot(selectedBackgroundColor)) selectedBackgroundColor = DS.selectedBackgroundColor!=null?DS.selectedBackgroundColor:"#333";
if (zot(selectedRollBackgroundColor)) selectedRollBackgroundColor = DS.selectedRollBackgroundColor!=null?DS.selectedRollBackgroundColor:rollBackgroundColor;
if (zot(color)) color = DS.color!=null?DS.color:"white";
if (zot(rollColor)) rollColor = DS.rollColor!=null?DS.rollColor:color;
if (zot(selectedColor)) selectedColor = DS.selectedColor!=null?DS.selectedColor:color;
if (zot(selectedRollColor)) selectedRollColor = DS.selectedRollColor!=null?DS.selectedRollColor:rollColor;
if (zot(backing)) backing = DS.backing!=null?DS.backing.clone():null;
if (zot(rollBacking)) rollBacking = DS.rollBacking!=null?DS.rollBacking.clone():null;
if (zot(align)) align=DS.align!=null?DS.align:"center";
if (zot(valign)) valign=DS.valign!=null?DS.valign:"center";
if (zot(labelAlign)) labelAlign=DS.labelAlign!=null?DS.labelAlign:align;
if (zot(labelValign)) labelValign=DS.labelValign!=null?DS.labelValign:valign;
if (zot(indent)) indent=DS.indent!=null?DS.indent:10;
if (zot(labelIndent)) labelIndent=DS.labelIndent!=null?DS.labelIndent:indent;
if (zot(labelIndentHorizontal)) labelIndentHorizontal=DS.labelIndentHorizontal!=null?DS.labelIndentHorizontal:labelIndent;
if (zot(labelIndentVertical)) labelIndentVertical=DS.labelIndentVertical!=null?DS.labelIndentVertical:labelIndent;
if (zot(currentEnabled)) currentEnabled = DS.currentEnabled!=null?DS.currentEnabled:false;
if (zot(currentSelected)) {
currentSelected = DS.currentSelected!=null?DS.currentSelected:true; // keep the highlight on after pressup
}
if (!currentSelected) currentEnabled = true; // button bar
if (zot(spacing)) spacing = DS.spacing!=null?DS.spacing:1;
if (zot(corner)) corner = DS.corner!=null?DS.corner:0;
if (zot(gradient)) gradient = DS.gradient!=null?DS.gradient:null;
if (zot(gloss)) gloss = DS.gloss!=null?DS.gloss:null;
if (zot(base)) base = DS.base!=null?DS.base:((corner==0&&!Array.isArray(corner))?"none":(vertical?"left":"bottom"));
if (zot(keyEnabled)) keyEnabled = DS.keyEnabled!=null?DS.keyEnabled:true;
if (zot(useTap)) useTap = DS.useTap!=null?DS.useTap:false;
if (zot(excludeCustomTap)) excludeCustomTap = DS.excludeCustomTap!=null?DS.excludeCustomTap:false;
if (zot(backdropColor)) backdropColor = DS.backdropColor!=null?DS.backdropColor:null;
if (zot(styleLabels)) styleLabels = DS.styleLabels!=null?DS.styleLabels:null;
if (zot(keyWrap)) keyWrap = DS.keyWrap!=null?DS.keyWrap:true;
if (base != "none" && corner != 0 && !Array.isArray(corner)) {
switch (base) {
case "bottom":
corner = [corner, corner, 0, 0]; break;
case "left":
corner = [0, corner, corner, 0]; break;
case "top":
corner = [0, 0, corner, corner]; break;
case "right":
corner = [corner, 0, 0, corner]; break;
}
} else if (!Array.isArray(corner)) {
corner = [corner, corner, corner, corner];
}
var that = this;
this.keyEnabled = keyEnabled;
var myIndex = 0; // local value for this.selectedIndex
var labels = [];
var buttons = [];
var button; var t;
var num = tabs.length;
var tabW = (width - spacing*(num-1))/num;
var tabH = (height - spacing*(num-1)-2)/num;
if (!zot(backdropColor)) {
// may be resized later
var backdrop = this.backdrop = new zim.Rectangle(width,height,backdropColor, null, null, null, null, null, false);
this.addChild(backdrop);
}
// Make a list be tab data objects if string, number, label or {} - other objects are ignored
var mix = false; // used to determine how to treat indent
var mixType;
function makeDataObject(list) {
for (var i=0; i width - spacing*(num-1)) {
// go back and assign proportional widths
for (i=0; i 0) {
newTabW = (num*tabW-(total-nonSpecifiedCount*tabW))/nonSpecifiedCount;
for (i=0; i maxWidth) maxWidth = t.label.width;
}
// create buttons
var hMaxWidth = 0;
function makeButtons(list, addStyle) {
var buttons = [];
var labels = [];
for (i=0; i hMaxWidth) hMaxWidth = button.width;
// apply events
if (useTap) {
button.tap(function (e) {
change(e.currentTarget.znum);
that.dispatchEvent("change");
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
});
} else {
button.zimTabEvent = button.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", function(e) {
change(e.currentTarget.znum);
that.dispatchEvent("change");
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
});
}
button.on("mousedown", function(e) {
that.buttonDown = e.currentTarget;
});
button.on("pressup", function() {
that.buttonDown = null;
});
labels.push(t.label);
buttons.push(button);
button.index = i;
}
return [buttons, labels];
}
var result = makeButtons(tabs);
buttons = result[0];
labels = result[1];
// finalize index, location, bounds
function prepareAllButtons() {
var lastX = 0; var lastY = 0; var t; var button;
for (i=0; i= index && myIndex <= index+num) myIndex = -1;
if (myIndex > index+num) myIndex -= num;
// remove listeners
for (i=index; itabs.length-1)?(keyWrap?0:tabs.length-1):next);
}
that.dispatchEvent("change");
that.dispatchEvent("keychange");
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
e.preventDefault();
}
};
window.addEventListener("keydown", that.keyEvent);
Object.defineProperty(this, 'selected', {
get: function() {
return buttons[myIndex];
},
set: function(value) {
if (zon) zogy("Tabs() - selected is read only - try selectedIndex");
}
});
Object.defineProperty(this, 'selectedIndex', {
get: function() {
return myIndex;
},
set: function(value) {
// change(Math.min(Math.max(value, 0), tabs.length-1));
change(value);
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
this.last = function() {
this.selectedIndex = this.buttons.length-1;
return this;
};
this.first = function() {
this.selectedIndex = 0;
return this;
};
Object.defineProperty(this, 'tabs', {
get: function() {
return myIndex;
},
set: function(value) {
change(Math.min(Math.max(value, 0), tabs.length-1));
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(this, 'color', {
get: function() {
if (that.buttons[0].tabItems) return that.buttons[0].tabItems.color;
else return color;
},
set: function(value) {
color = value;
if (that.buttons[0].tabInfo) {
for (var i=0; i= 0 && tabNum < that.tabs.length) {
that.tabs[tabNum].selectedIndex = myIndex % cols;
}
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
}
});
if (zot(selectedIndex)) selectedIndex=DS.selectedIndex!=null?DS.selectedIndex:0;
that.selectedIndex = selectedIndex;
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Pad(width, cols, rows, keys, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, spacing, currentEnabled, corner, labelColor, gradient, gloss, backing, rollBacking, wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal, waitEnabled, selectedIndex, style, this.group, inherit));
};
this.dispose = function(a,b,disposing) {
zim.loop(rowTabs, function (t) {
t.dispose();
});
this.labels = this.buttons = tabs = this.tabs = null;
r = rowTabs = that.rowTabs = null;
if (!disposing) this.zimContainer_dispose(true);
};
};
zim.extend(zim.Pad, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-66
//
/*--
zim.DPad = function(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, group, inherit)
DPad
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A DPad (Directional Pad) can be used to control x and y values
This is primarily handy on mobile where a substitute for keypresses is needed
The DPad can be set up for all directions, horizontal or vertical
The DPad can be passed in to a ZIM MotionController to control an object
See: https://zimjs.com/ten/dpad.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var dPadH = new DPad().pos(50,50,false,true);
new MotionController({
target:new Circle().center(),
type:dPadH,
speed:mobile()?100:80,
boundary:new Boundary(0,0,stageW,stageH)
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
axis - (default "all") set to "horizontal" or "vertical" or "all". Appropriate arrows will show
width - (default 100) width of DPad backgroundColor - (default "#777") the background color of a deselected key when not rolled over
backgroundColor - (default "#666") the background color (any zim or html color)
indicatorColor - (default "#ddd") the color of the arrows
indicatorPressColor - (default "#eee") the color of the arrows as pressed
indicatorScale - (default 1) the scale of the arrows
indicatorRadius - (default null) set the indicator radius
innerCircle - (default true) set to false to not show an inner circle
innerScale - (default .5) the scale relative to the indicator
activeRadius - (default width*2) radius at which the DPad works
clamp - (default true) set to false to not limit the value between -1 and 1
logo - (default false) set to true to show the letter D in the DPad - or add your own
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
dirX, dirY - the x and y values for the DPad - between -1 and 1 if clamp is set
these can be multiplied by a factor to adjust speed - or use speed parameter of associated MotionController
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
enabled - default is true - set to false to disable
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event with dirX and dirY provided as well on the event object
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+66.2
zim.DPad = function(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, group, inherit) {
var sig = "axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, group, inherit";
var duo; if (duo = zob(zim.DPad, arguments, sig, this)) return duo;
z_d("66.2");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "DPad";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(axis)) axis = DS.axis!=null?DS.axis:"all";
if (zot(width)) width = DS.width!=null?DS.width:100;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#666666";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(indicatorColor)) indicatorColor = DS.indicatorColor!=null?DS.indicatorColor:"#dddddd";
if (zot(indicatorPressColor)) indicatorPressColor = DS.indicatorPressColor!=null?DS.indicatorPressColor:"#eeeeee";
if (zot(indicatorScale)) indicatorScale = DS.indicatorScale!=null?DS.indicatorScale:1;
if (zot(indicatorRadius)) indicatorRadius = DS.indicatorRadius!=null?DS.indicatorRadius:null;
if (zot(innerCircle)) innerCircle = DS.innerCircle!=null?DS.innerCircle:true;
if (zot(innerScale)) innerScale = DS.innerScale!=null?DS.innerScale:.5;
if (zot(activeRadius)) activeRadius = DS.activeRadius!=null?DS.activeRadius:width; // note, twice diameter
if (zot(clamp)) clamp = DS.clamp!=null?DS.clamp:true;
if (zot(logo)) logo = DS.logo!=null?DS.logo:false;
var that = this;
this.axis = axis;
var outer = this.outer = new zim.Circle(width/2, backgroundColor, borderColor, borderWidth).addTo(this);
var inner = this.inner = new zim.Circle(width*innerScale/2, "rgba(0,0,0,.2)").center(this);
if (logo) this.logo = new zim.Label({text:"D", bold:true}).center(inner).mov(1,2).alp(.3);
var arrows = new zim.Container().addTo(this);
var arrowSize = (width-borderWidth)*.2*indicatorScale;
var numArrows = 8; // default all
if (axis == "vertical") {
numArrows = 2;
} else if (axis == "horizontal") {
numArrows = 2;
arrows.rotation = 90;
} else if (axis == "both") {
numArrows = 4;
}
zim.loop(numArrows, function (i, total) {
new zim.Triangle(arrowSize, arrowSize, arrowSize, indicatorColor).addTo(arrows).reg(null, zot(indicatorRadius)?(width-borderWidth)*.475:indicatorRadius).rot(i*360/total);
});
var startX = 0;
var startY = 0;
var stage;
var p;
var currentEvent;
var firstTime = true;
this.on("mousedown", function (e) {
stage = e.target.stage;
currentEvent = e;
arrows.loop(function (arrow) {
arrow.color = indicatorPressColor;
});
if (firstTime) {
that.ticker = zim.Ticker.add(function () {
calculatePos();
});
} else {
zim.Ticker.add(that.ticker);
}
});
this.on("pressmove", function (e) {
currentEvent = e;
});
this.on("pressup", function (e) {
zim.Ticker.remove(that.ticker);
that.dirX = that.dirY = 0;
arrows.loop(function (arrow) {
arrow.color = indicatorColor;
});
if (that.stage) that.stage.update();
});
function calculatePos(){
var e = currentEvent;
startX = e.stageX/zim.scaX;
startY = e.stageY/zim.scaY;
p = that.globalToLocal(startX, startY);
e = new createjs.Event("change");
e.dirX = ((p.x+activeRadius)/(activeRadius*2)-.5)*2;
e.dirY = ((p.y+activeRadius)/(activeRadius*2)-.5)*2;
if (clamp) {
e.dirX = zim.constrain(e.dirX, -1, 1);
e.dirY = zim.constrain(e.dirY, -1, 1);
}
that.dirX = e.dirX;
that.dirY = e.dirY;
that.dispatchEvent(e);
}
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
}
});
zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.DPad(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, this.group, inherit));
};
this.dispose = function(a,b,disposing) {
if (this.ticker) zim.Ticker.remove(this.ticker);
if (!disposing) this.zimContainer_dispose(true);
return true;
};
};
zim.extend(zim.DPad, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-66.2
//
/*--
zim.Radial = function(labels, size, font, height, coreRadius, coreColor, startAngle, totalAngle, angles, flip, shiftVertical, icons, rollIcons, rotateIcons, iconsShiftVertical, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, selectedIndex, style, group, inherit)
Radial
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A radial ring with selectable buttons with lables or icons
Used internally by ZIM RadialMenu which has expandable rings for a hierarchical interface
Radial uses LabelOnArc for labels
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var radial = new Radial(["one", "two", "three", "four"]).center();
radial.change(function () {
zog(radial.selectedIndex);
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
labels - (default ["A", "B", "C", "D", "E"]) an array of text or ZIM Label objects for buttons
size - (default 30) label size
font - (default "verdana") the font - can also import fonts in Frame() asset parameter or frame.loadAssets()
startAngle - (default null) will start first button centered at top - see also totalAngle
setting an angle will start left side of first button at this angle
with 0 being the top (note, ZIM angles usually start along x axis - but not here)
totalAngle - (default 360) set to use only a portion of the circle - see also startAngle
angles - (default null) can set an array of angles for center of the buttons
can use angles property toString() to get existing angle data
this can be modified to suit and passed into this parameter for unequal button sizes
flip - (default true) flip the text between 90 and -180 (from 0 at top)
shiftRadial - (default 0) amount to shift text in radially
icons - (default null) set to an array of objects that will go under the text
can set the labels to ["", "", "", etc.] to hide the text
icons should be centerReg({add:false}) to ensure centered placement
rollIcons - (default null) set to an array of objects to replace icon when rolled over
rotateIcons - (default false) set to true to rotate icons around radial
iconsShiftRadial - (default 0) amount to shif the icons radially
height - (default 60) height of radial - not including core
coreRadius - (default 100) the radius of the core
this is fairly large but can sca(.5) the radial after creating, etc.
coreColor - (default #333) the color of the core
backgroundColor - |ZIM VEE| - (default "#666") the background color of a button
ZIM VEE means you can specify different colors for instance: series(blue, green, red, yellow)
these would then be the color order of the buttons - same for rollBackgroundColor, etc.
rollBackgroundColor - |ZIM VEE| - (default "#777") the rollover background color of a button
selectedBackgroundColor - |ZIM VEE| - (default "#444") the background color of the selected button
selectedRollBackgroundColor - |ZIM VEE| - (default selectedBackgroundColor) the roll background color of the selected button
backdropColor - (default clear) set to change the color behind the radial - including spacingOuter
color - |ZIM VEE| - (default "white") the text color of the button
rollColor - |ZIM VEE| - (default color) the rollover text color of the button
selectedColor - |ZIM VEE| - (default color) the text color of the selected button
selectedRollColor - |ZIM VEE| - (default color) the rollover text color of the selected button
borderColor - (default #333) color of the button border
borderWidth - (default 2) width of the button border
gradient - (default null) set to a number between 0 and 1 - would suggest .1 for gradient on button
gap - (default 6 pixels or 3 degrees if gapAsAngle is true) gap between buttons
gapAsAngle - (default false) set to true set gap as angle
spacing - (default 6) radial spacing around button from core or edge of backdrop
spacingInner - (default spacing) inside radial spacing from core
spacingOuter - (default spacing) outside radial spacing from edge of backdrop
currentEnabled - (default false) set to true to make selected key pressable (for change event)
currentSelected - (default true) set to true to make selected key show selected colors
selectedIndex - (default 0) - set the selectedIndex at start
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedIndex - gets or sets the selected index of the pad
text - gets current selected label text
label - gets current selected label object
selected - gets the selected button - selected.enabled = true, etc.
buttons - a container of buttons
each button has label and icon properties
angles - an array of angles to the center of the buttons
can log angles.toString() to get angle data
this can be adjusted and passed in to the angles parameter for unequal size buttons
core - a reference to the core circle object
backdrop - a reference to the backdrop circle
enabled - default is true - set to false to disable
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "change" event when the button changes (but not when setting selectedIndex property)
see also currentEnabled to get change event for each press - or use tap()
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+66.4
zim.Radial = function(labels, size, font, height, coreRadius, coreColor, startAngle, totalAngle, angles, flip, shiftRadial, icons, rollIcons, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, selectedIndex, style, group, inherit) {
var sig = "labels, size, font, height, coreRadius, coreColor, startAngle, totalAngle, angles, flip, shiftRadial, icons, rollIcons, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, selectedIndex, style, group, inherit";
var duo; if (duo = zob(zim.Radial, arguments, sig, this)) return duo;
z_d("66.4");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Radial";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(labels)) labels = DS.labels!=null?DS.labels:["A", "B", "C", "D", "E"];
if (zot(size)) size = DS.size!=null?DS.size:30;
if (zot(font)) font = DS.font!=null?DS.font:"verdana";
if (zot(startAngle)) startAngle = DS.startAngle!=null?DS.startAngle:null; // top center
if (zot(totalAngle)) totalAngle = DS.totalAngle!=null?DS.totalAngle:360;
if (zot(angles)) angles = DS.angles!=null?DS.angles:null;
if (zot(flip)) flip = DS.flip!=null?DS.flip:true;
if (zot(shiftRadial)) shiftRadial = DS.shiftRadial!=null?DS.shiftRadial:0;
if (zot(icons)) icons = DS.icons!=null?DS.icons:null;
if (zot(rollIcons)) rollIcons = DS.rollIcons!=null?DS.rollIcons:null;
if (zot(rotateIcons)) rotateIcons = DS.rotateIcons!=null?DS.rotateIcons:false;
if (zot(iconsShiftRadial)) iconsShiftRadial = DS.iconsShiftRadial!=null?DS.iconsShiftRadial:0;
if (zot(height)) height = DS.height!=null?DS.height:60;
if (zot(coreRadius)) coreRadius = DS.coreRadius!=null?DS.coreRadius:100;
if (zot(coreColor)) coreColor = DS.coreColor!=null?DS.coreColor:"#333";
if (zot(backdropColor)) backdropColor = DS.backdropColor!=null?DS.backdropColor:zim.clear;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#666";
if (zot(rollBackgroundColor)) rollBackgroundColor = DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#777";
if (zot(selectedBackgroundColor)) selectedBackgroundColor = DS.selectedBackgroundColor!=null?DS.selectedBackgroundColor:"#444";
if (zot(selectedRollBackgroundColor)) selectedRollBackgroundColor = DS.selectedRollBackgroundColor!=null?DS.selectedRollBackgroundColor:selectedBackgroundColor;
if (zot(color)) color = DS.color!=null?DS.color:"white";
if (zot(rollColor)) rollColor = DS.rollColor!=null?DS.rollColor:color;
if (zot(selectedColor)) selectedColor = DS.selectedColor!=null?DS.selectedColor:color;
if (zot(selectedRollColor)) selectedRollColor = DS.selectedRollColor!=null?DS.selectedRollColor:rollColor;
if (zot(borderColor)) borderColor=DS.borderColor!=null?DS.borderColor:"#333";
if (zot(borderWidth)) borderWidth=DS.borderWidth!=null?DS.borderWidth:2; // 0
if (zot(gapAsAngle)) gapAsAngle=DS.gapAsAngle!=null?DS.gapAsAngle:false;
if (zot(gap)) gap=DS.gap!=null?DS.gap:(gapAsAngle?3:6);
if (zot(gradient)) gradient=DS.gradient!=null?DS.gradient:null;
if (gradient === true) gradient = .1;
if (zot(spacing)) spacing=DS.spacing!=null?DS.spacing:6;
if (zot(spacingInner)) spacingInner=DS.spacingInner!=null?DS.spacingInner:spacing;
if (zot(spacingOuter)) spacingOuter=DS.spacingOuter!=null?DS.spacingOuter:spacing;
if (zot(currentEnabled)) currentEnabled=DS.currentEnabled!=null?DS.currentEnabled:false;
if (zot(currentSelected)) currentSelected=DS.currentSelected!=null?DS.currentSelected:true;
var that = this;
var innerRadius = this.innerRadius = coreRadius+spacingInner;
var outerRadius = this.outerRadius = innerRadius + height;
this.setBounds(-outerRadius, -outerRadius, outerRadius*2, outerRadius*2);
var backdrop = this.backdrop = new zim.Circle(outerRadius+spacingOuter, backdropColor).center(this);
if (coreRadius > 0) this.core = new zim.Circle(coreRadius, coreColor).center(this);
if (angles && angles.length < labels.length-1) {
if (zon) zogy("Radial() - not enough angles provided");
return this;
}
if ((labels && labels.length > 0) || (icons && icons.length > 0)) {
var total;
if (labels && labels.length > 0) total = labels.length;
if (icons && icons.length > 0) {
if (total > 0) total = Math.min(icons.length, total);
else total = icons.length;
}
if (rollIcons && rollIcons.length < total) {
for (var j=0; j 0) { // no border specified or a border > 0
if (!zot(borderColor) || !zot(borderWidth)) { // either a border color or thickness
if (zot(borderColor)) borderColor = "black";
button.borderColorCommand = g.s(borderColor).command;
button.borderWidthCommand = g.ss(borderWidth).command;
}
}
var a0 = (lastAngle-90-segmentAngle/2)*Math.PI/180;
var a1 = (lastAngle-90+segmentAngle/2)*Math.PI/180;
var a2 = (lastAngle-90+(segmentAngle+gap-gapInner)/2)*Math.PI/180;
var a3 = (lastAngle-90-(segmentAngle+gap-gapInner)/2)*Math.PI/180;
g.arc(0, 0, outerRadius, a0, a1, false);
g.arc(0, 0, innerRadius, a2, a3, true).cp();
if (gradient) {
g.s().ss().rf(["rgba(0,0,0,"+gradient+")","rgba(255,255,255,"+gradient+")"], [0, 1], 0, 0, innerRadius, 0, 0, outerRadius);
g.arc(0, 0, outerRadius, a0, a1, false);
g.arc(0, 0, innerRadius, a2, a3, true).cp();
}
button.cursor = "pointer";
button.zimOverEvent = button.on("mouseover", function(e) {
var button = e.target;
button.colorCommand.style = (button==that.selected&¤tSelected)?button.selectedRollBackgroundColor:button.rollBackgroundColor;
if (button.label) button.label.color = (button==that.selected&¤tSelected)?button.selectedRollColor:button.rollColor;
if (rollIcons) {
button.holder.removeAllChildren();
rollIcons[button.num].loc(1,0,button.holder);
}
if (that.stage) that.stage.update();
});
button.zimOutEvent = button.on("mouseout", function(e) {
var button = e.target;
button.colorCommand.style = (button==that.selected&¤tSelected)?button.selectedBackgroundColor:button.backgroundColor;
if (button.label) button.label.color = (button==that.selected&¤tSelected)?button.selectedColor:button.color;
if (rollIcons) {
button.holder.removeAllChildren();
if (icons) icons[button.num].loc(1,0,button.holder);
}
if (that.stage) that.stage.update();
});
button.zimDownEvent = button.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", function(e) {
var button = e.target;
var diff = button !== that.selected;
that.lastSelected = that.selected;
myIndex = button.num;
if (currentSelected) {
if (diff) {
if (that.selected) {
that.selected.colorCommand.style = that.selected.backgroundColor;
if (that.selected.label) that.selected.label.color = that.selected.color;
}
that.selected = button;
that.label = button.label;
if (that.label) that.text = that.label.text;
that.icon = button.icon;
button.colorCommand.style = button.selectedRollBackgroundColor;
if (button.label) button.label.color = button.selectedRollColor;
} else {
if (!currentEnabled) {
myIndex = -1;
that.selected = null;
that.label = null;
that.text = null;
that.icon = null;
button.colorCommand.style = button.rollBackgroundColor;
if (button.label) button.label.color = button.rollColor;
}
}
} else {
that.selected = button;
that.label = button.label;
if (that.label) that.text = that.label.text;
that.icon = button.icon;
}
that.dispatchEvent("change");
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
});
if (icons && icons.length > 0) {
var h = innerRadius+height/2+iconsShiftRadial;
var holder = button.holder = new zim.Container(3, h).addTo(this).reg(1,h).rot(lastAngle);
holder.mouseChildren = false;
holder.mouseEnabled = false;
button.icon = icons[i];
icons[i].loc(1,0,holder);
if (!rotateIcons) icons[i].rotation = -lastAngle;
} // end icons
if (labels && labels.length > 0) {
// var buttons = this.buttons = new zim.Container(-s/2, -s/2, s, s).centerReg(this);
var loa;
if (labels[i].type != "LabelOnArc") {
var label = (labels[i].type=="Label"?labels[i]:new zim.Label({text:labels[i], size:size, font:font, color:color, style:style, inherit:inherit}));
loa = new zim.LabelOnArc({
label: label,
color:color,
size:size,
spacing:-5,
flip:(flip && lastAngle>90 && lastAngle<270),
radius:innerRadius+(height-label.height)/2+2+shiftRadial,
style:style,
inherit:inherit
});
} else {
loa = labels[i];
}
labels[i] = loa;
button.label = loa;
loa.center(this).rot(lastAngle);
loa.mouseChildren = false;
loa.mouseEnabled = false;
} // end labels
if (i==labels.length-1) continue;
var segmentAngle2 = angles?angles[i+1]:segmentAngle;
lastAngle += (segmentAngle+segmentAngle2)/2+gap;
}
if (!zot(startAngle)) {
that.rotation += that.buttons.getChildAt(0).angle/2;
}
}
var myIndex = null;
Object.defineProperty(this, 'selectedIndex', {
get: function() {
return myIndex;
},
set: function(value) {
var button;
if (that.buttons) button = that.buttons.getChildAt(value);
if (button !== that.selected) {
if (that.selected) {
that.selected.colorCommand.style = that.selected.backgroundColor;
if (that.selected.label) that.selected.label.color = that.selected.color;
}
that.selected = button;
if (button) {
if (currentSelected) button.colorCommand.style = button.selectedRollBackgroundColor;
if (button.label) {
if (currentSelected) button.label.color = button.selectedColor;
that.text = button.label.text;
}
}
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
if (zot(selectedIndex)) selectedIndex=DS.selectedIndex!=null?DS.selectedIndex:0;
that.selectedIndex = selectedIndex;
zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Radial(labels, size, font, height, coreRadius, coreColor, startAngle, totalAngle, angles, flip, shiftRadial, icons, rollIcons, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, selectedIndex, style, this.group, inherit));
};
};
zim.extend(zim.Radial, zim.Container, "clone", "zimContainer", false);
//-66.4
/*--
zim.RadialMenu = function(menu, size, font, height, coreRadius, coreColor, title, titleIcon, startAngle, totalAngle, flip, shiftRadial, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, open, under, style, group, inherit)
RadialMenu
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
An expanding hierarchy menu of button rings - using ZIM Radial objects.
The menu is specified by a menu parameter in the format of a ZIM Hierarchy object.
Styles for each ring can be specified in the menu object.
Icons for each ring can be specified in the styles.
See https://zimjs.com/ten/radial.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var menu = {
"one":[1,2,3,4], // an array is okay as all items are leaf nodes (end nodes)
"two":{ // an object literal is required as one or more items hold other items
"1":[], // this holds nothing (a leaf node) but still needs an empty array
"2":["a", "b", "c"], // this holds a linear list - all leaf nodes
"3":{ // this holds another nested list where at least one item holds more
"emotions":["love","hate","happy","sad"],
"flavors":["sweet","sour","bland","spicy"]
}
},
"three":[1,2,3,4,5,6],
"four":[1,2,3,4,5,6,7,8]
}
new RadialMenu(menu).sca(.5).center();
stage.update();
// OR ADD STYLES
// see https://zimjs.com/ten/radial.html for full example
// any Radial parameters can go in the styles:{} brackets
// including icons and rollIcons
// and can use series to apply background colors and colors to individual buttons
// PS - this is the EXTRA version of the simple ZIM Hierarchy format
// here we pass styles as an extra property - list is required
// styles is optional but used by ZIM RadialMenu to apply associated styles
var menu = {
list:{
"one":{
list:["A","B","C","D"], // an array is okay as all items are leaf nodes (end nodes)
styles:{backgroundColor:blue}
},
"two":{
list:{ // an object literal is required as one or more items hold other items
"1":[], // this holds nothing (a leaf node) but still needs an empty array
"2":{
list:["a", "b", "c"], // this holds a linear list - all leaf nodes
styles:{}
},
"3":{ // this holds another nested list where at least one item holds more
list:{
"emotions":{
list:["love","hate","happy","sad"],
styles:{}
},
"flavors":{
list:["sweet","sour","bland","spicy"] ,
styles:{}
}
},
styles:{}
}
},
styles:{}
},
"three":{
list:[1,2,3,4,5,6],
styles:{}
},
"four":{
list:[1,2,3,4,5,6,7,8],
styles:{}
}
},
// the styles for the first list
// here we make each backgroundColor a different color
styles:{backgroundColor:series(red,green,blue,yellow)}
}
new RadialMenu(menu).sca(.5).center();
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
menu - (default a simple menu) a ZIM Hierarchy (simple, simple EXTRA or complex)
that holds the menu labels and optionally styles
see the ZIM RadialMenu examples and the format descriptions of ZIM Hierarchy for details
size - (default 30) label size
font - (default "verdana") the font - can also import fonts in Frame() asset parameter or frame.loadAssets()
startAngle - (default null) will start first button centered at top - see also totalAngle
setting an angle will start left side of first button at this angle
with 0 being the top (note, ZIM angles usually start along x axis - but not here)
totalAngle - (default 360) set to use only a portion of the circle - see also startAngle
flip - (default true) flip the text between 90 and -180 (from 0 at top)
shiftRadial - (default 0) amount to shift text in radially
rotateIcons - (default false) set to true to rotate icons around radial
iconsShiftRadial - (default 0) amount to shif the icons radially
height - (default 60) height of radial - not including core or previous radials
coreRadius - (default 100) the radius of the core
this is fairly large but can sca(.5) the radial after creating, etc.
coreColor - (default #333) the color of the core
title - (default "MENU") the label text in the core
titleIcon - (default null) an object to put under the title
** FOR BELOW: see menu parameter where colors can be set per ring and per button for ZIM VEE colors
backgroundColor - |ZIM VEE| - (default "#666") the background color of a button
ZIM VEE means you can specify different colors for instance: series(blue, green, red, yellow)
these would then be the color order of the buttons - same for rollBackgroundColor, etc.
rollBackgroundColor - |ZIM VEE| - (default "#777") the rollover background color of a button
selectedBackgroundColor - |ZIM VEE| - (default "#444") the background color of the selected button
selectedRollBackgroundColor - |ZIM VEE| - (default selectedBackgroundColor) the roll background color of the selected button
backdropColor - (default clear) set to change the color behind the radial - including spacingOuter
color - |ZIM VEE| - (default "white") the text color of the button
rollColor - |ZIM VEE| - (default color) the rollover text color of the button
selectedColor - |ZIM VEE| - (default color) the text color of the selected button
selectedRollColor - |ZIM VEE| - (default color) the rollover text color of the selected button
borderColor - (default #333) color of the button border
borderWidth - (default 2) width of the button border
gradient - (default null) set to a number between 0 and 1 - would suggest .1 for gradient on button
gap - (default 6 pixels or 3 degrees if gapAsAngle is true) gap between buttons
gapAsAngle - (default false) set to true set gap as angle
spacing - (default 6) radial spacing around button from core or edge of backdrop
spacingInner - (default spacing) inside radial spacing from nearest inside object
spacingOuter - (default spacing) outside radial spacing from edge of backdrop
currentEnabled - (default false) set to true to make selected key pressable (for change event)
currentSelected - (default true) set to true to make selected key show selected colors
open - (default false) set to true to start with first menu open
under - (default true) set to false to open menu rings in the top layer (usually under just in case there is a backdrop)
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
closeRings(num) - close menu rings - default is all rings but use 1 to close the outer ring, 2 to close the two outer rings, etc.
see the outerLevel property for the current outer ring number with core being 0
opening rings programmatically is not yet supported but may be in the future
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedIndex - gets the selected index of the outer ring (setting may come soon)
selectedLevel - gets the index of the level with the latest selection - the core is 0
selectedMenu - gets a reference to the selected menu
outerLevel - gets the index number of the outside level - the core is 0
outerMenu - gets a reference to the outer menu
text - gets current selected label text
label - gets current selected label object
selected - gets the selected button
core - a reference to the core circle object
enabled - default is true - set to false to disable
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "change" event when the button changes (but not when setting selectedIndex property)
see also selectedIndex, selectedLevel, selected and text properties
see also currentEnabled to get change event for each press - or use tap()
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+66.6
zim.RadialMenu = function(menu, size, font, height, coreRadius, coreColor, title, titleIcon, startAngle, totalAngle, flip, shiftRadial, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, open, under, style, group, inherit) {
var sig = "menu, size, font, height, coreRadius, coreColor, title, titleIcon, startAngle, totalAngle, flip, shiftRadial, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, open, under, style, group, inherit";
var sigList = sig.split(", ");
var duoTest = false;
if (menu && menu.constructor === {}.constructor) {
for (var i in menu) {
if (sigList.indexOf(i) >= 0) {
duoTest = true;
break;
}
}
}
if (menu && duoTest) {var duo; if (duo = zob(zim.RadialMenu, arguments, sig, this)) return duo;}
z_d("66.6");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "RadialMenu";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(menu)) menu = DS.menu!=null?DS.menu:{A:{A1:["AA1", "AA2", "AA3", "AA4"],A2:[],A3:[]},B:["B1","B2","B3","B4","B5","B6"],C:[]};
if (zot(size)) size = DS.size!=null?DS.size:30;
if (zot(font)) font = DS.font!=null?DS.font:"verdana";
if (zot(startAngle)) startAngle = DS.startAngle!=null?DS.startAngle:null; // top center
if (zot(totalAngle)) totalAngle = DS.totalAngle!=null?DS.totalAngle:360;
if (zot(flip)) flip = DS.flip!=null?DS.flip:true;
if (zot(rotateIcons)) rotateIcons = DS.rotateIcons!=null?DS.rotateIcons:false;
if (zot(shiftRadial)) shiftRadial = DS.shiftRadial!=null?DS.shiftRadial:0;
if (zot(iconsShiftRadial)) iconsShiftRadial = DS.iconsShiftRadial!=null?DS.iconsShiftRadial:0;
if (zot(height)) height = DS.height!=null?DS.height:60;
if (zot(coreRadius)) coreRadius = DS.coreRadius!=null?DS.coreRadius:100;
if (zot(coreColor)) coreColor = DS.coreColor!=null?DS.coreColor:"#333";
if (zot(title)) title = DS.title!=null?DS.title:"MENU";
if (zot(titleIcon)) titleIcon = DS.titleIcon!=null?DS.titleIcon:null;
if (zot(backdropColor)) backdropColor = DS.backdropColor!=null?DS.backdropColor:zim.clear;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#666";
if (zot(rollBackgroundColor)) rollBackgroundColor = DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#777";
if (zot(selectedBackgroundColor)) selectedBackgroundColor = DS.selectedBackgroundColor!=null?DS.selectedBackgroundColor:"#444";
if (zot(selectedRollBackgroundColor)) selectedRollBackgroundColor = DS.selectedRollBackgroundColor!=null?DS.selectedRollBackgroundColor:selectedBackgroundColor;
if (zot(color)) color = DS.color!=null?DS.color:"white";
if (zot(rollColor)) rollColor = DS.rollColor!=null?DS.rollColor:color;
if (zot(selectedColor)) selectedColor = DS.selectedColor!=null?DS.selectedColor:color;
if (zot(selectedRollColor)) selectedRollColor = DS.selectedRollColor!=null?DS.selectedRollColor:rollColor;
if (zot(borderColor)) borderColor=DS.borderColor!=null?DS.borderColor:"#333";
if (zot(borderWidth)) borderWidth=DS.borderWidth!=null?DS.borderWidth:2; // 0
if (zot(gapAsAngle)) gapAsAngle=DS.gapAsAngle!=null?DS.gapAsAngle:false;
if (zot(gap)) gap=DS.gap!=null?DS.gap:(gapAsAngle?3:6);
if (zot(spacing)) spacing=DS.spacing!=null?DS.spacing:6;
if (zot(gradient)) gradient=DS.gradient!=null?DS.gradient:null;
if (gradient === true) gradient = .1;
if (zot(spacingInner)) spacingInner=DS.spacingInner!=null?DS.spacingInner:spacing;
if (zot(spacingOuter)) spacingOuter=DS.spacingOuter!=null?DS.spacingOuter:spacing;
if (zot(currentEnabled)) currentEnabled=DS.currentEnabled!=null?DS.currentEnabled:false;
if (zot(currentSelected)) currentSelected=DS.currentSelected!=null?DS.currentSelected:true;
if (zot(open)) open=DS.open!=null?DS.open:false;
if (zot(under)) under=DS.under!=null?DS.under:true;
var that = this;
var eventType = (!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click";
var lastSelected = null;
var core = this.core = new zim.Circle({radius:coreRadius, color:coreColor, style:style, inherit:inherit}).addTo(this);
if (titleIcon) this.titleIcon = titleIcon.center(core);
if (title) this.title = new zim.Label({text:title, size:size, font:font, color:color, style:style, inherit:inherit}).center(core);
core.cursor = "pointer";
core.on(eventType, function(e) {
that.leafNode = false;
if (radials.length == 0) {
changeRadial();
} else {
zim.loop(radials, function (radial) {
radial.selectedIndex = -1;
radial.removeFrom();
radials = [];
});
that.outerLevel = 0;
that.selected = that.outerMenu = that.selectedMenu = that.text = null;
}
if (currentEnabled || that.selected != lastSelected) that.dispatchEvent("change");
lastSelected = that.selected;
if (that.stage) that.stage.update();
});
this.closeRings = function(num) {
if (zot(num)) num = that.outerLevel;
var lev = that.outerLevel - num;
zim.loop(radials, function (radial, i) {
if (i>lev-1) {
radial.removeFrom();
radial.selectedIndex = -1;
radials.pop();
}
}, true); // loop backwards
that.outerLevel = lev;
that.outerMenu = radials[radials.length-1];
if (that.outerMenu) that.outerMenu.selectedIndex = -1;
that.selected = that.selectedMenu = that.text = null;
if (radials[radials.length-2]) {
that.selectedMenu = radials[radials.length-2];
that.selectedIndex = that.selectedMenu.selectedIndex;
}
else that.selectedIndex = -1;
if (that.selected != lastSelected) that.dispatchEvent("change");
lastSelected = that.selected;
if (that.stage) that.stage.update();
};
// handle menu data
var menus = {}; // holds created menus and does not remove them
var tree;
var ids;
that.outerLevel = 0;
if (menu.constructor == {}.constructor) {
menu = {core:menu};
tree = that.tree = new zim.Hierarchy(menu);
ids = tree.getLinearIDs();
}
that.lastRadial = null;
var radials = this.radials = [];
if (open) {changeRadial();}
function changeRadial(currentRadial) {
var level, radius;
if (!currentRadial) { // from core
level = 0;
radius = coreRadius;
} else {
// figure out the level based on currentRadial
level = currentRadial.ringLevel;
}
// remove previous outer selections
zim.loop(radials, function (radial, i) {
if (i>level-1) {
radial.removeFrom();
radial.selectedIndex = -1;
radials.pop();
}
}, true); // loop backwards
var currentButton;
if (currentRadial) currentButton = currentRadial.selected;
if (currentButton) {
var id = currentButton.id;
radius = currentRadial.outerRadius;
makeRadial(id, level+1, radius);
} else if (!currentRadial) {
makeRadial("id0", level+1, radius);
} // else turning off button on current radial
that.selected = currentButton;
if (that.selected) {
that.selectedMenu = radials[that.selected.menu.ringLevel-1];
that.selectedIndex = that.selected.num;
if (that.selected.label) that.text = that.selected.label.text;
else that.text = null;
} else {
if (currentEnabled && currentRadial) {
that.selectedIndex = currentRadial.selectedIndex;
that.label = currentRadial.label;
that.text = currentRadial.text;
that.icon = currentRadial.icon;
that.selectedMenu = currentRadial;
} else {
that.text = null;
that.selectedIndex = -1;
that.selectedMenu = null;
}
}
if (that.stage) that.stage.update();
}
function makeRadial(id, level, radius) {
if (level) that.outerLevel = level;
var currentMenu;
if (!menus[id]) {
var data = tree.getData(id);
var list = data.list;
if (list && !zim.isEmpty(list)) {
var props = {
labels:tree.getLinearList(list),
coreRadius:radius,
size:size,
font:font,
startAngle:startAngle,
totalAngle:totalAngle,
flip:flip,
rotateIcons:rotateIcons,
shiftRadial:shiftRadial,
iconsShiftRadial:iconsShiftRadial,
height:height,
coreColor:zim.clear,
backdropColor:backdropColor,
backgroundColor:backgroundColor,
rollBackgroundColor:rollBackgroundColor,
selectedBackgroundColor:selectedBackgroundColor,
selectedRollBackgroundColor:selectedRollBackgroundColor,
color:color,
rollColor:rollColor,
selectedColor:selectedColor,
selectedRollColor:selectedRollColor,
borderColor:borderColor,
borderWidth:borderWidth,
gapAsAngle:gapAsAngle,
gap:gap,
gradient:gradient,
spacingInner:spacingInner,
spacingOuter:spacingOuter,
currentSelected:currentSelected,
currentEnabled:currentEnabled,
style:style,
inherit:inherit
};
var obj = tree;
if (data.styles) {
props = zim.merge(props, data.styles);
}
currentMenu = menus[id] = new zim.Radial(props);
ids = tree.getLinearIDs(list);
currentMenu.buttons.loop(function (button, i) {
button.menu = currentMenu;
button.id = ids[i];
});
currentMenu.ringLevel = that.outerLevel;
currentMenu.selectedIndex = -1;
currentMenu.on("change", function(e) {
that.leafNode = false;
changeRadial(e.target);
if (currentEnabled || that.selected != lastSelected) that.dispatchEvent("change");
lastSelected = that.selected;
});
}
}
if (menus[id]) {
radials.push(menus[id]);
menus[id].center(that);
if (under) menus[id].bot();
} else {
that.leafNode = true;
that.outerLevel -= 1;
}
that.outerMenu = currentMenu;
}
zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.RadialMenu(menu, size, font, height, coreRadius, coreColor, title, titleIcon, startAngle, totalAngle, flip, shiftRadial, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, open, under, style, this.group, inherit));
};
};
zim.extend(zim.RadialMenu, zim.Container, "clone", "zimContainer", false);
//-66.6
/*--
zim.ColorPicker = function(width, colors, cols, spacing, greyPicker, alphaPicker, startBackgroundColor, draggable, shadowColor, shadowBlur, buttonBar, circles, indicator, backgroundColor, keyArrows, container, selectedIndex, selectedColor, style, group, inherit)
ColorPicker
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A traditional color picker which shows 256 Web colors by default or custom colors.
Can additionally show 16 greys and / or an alpha slider.
Picking on a color sets the swatch color and the selectedColor property.
OK dispatches a "change" event if the color changed or a close event if not.
The X dispatches a "close" event.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var cp = new ColorPicker();
cp.center();
cp.on("change", function() {
zog(cp.selectedColor); // #ffcc99, etc. after pressing OK
zog(cp.selectedAlpha); // 0-1
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 500) the width of the color picker
colors - (default 256 Web colors) an optional list of colors ["red", "#CCC", etc.]
cols - (default 10) how many columns to use if you pass in custom colors
spacing - (default 2) is the space between the color squares
greyPicker - (default true unless one row) shows an extra 16 greys (set to false to hide these)
for the default colors it also includes 2 starting colors that record last picked colors
alphaPicker - (default true unless one row) shows an alpha slider (set to false to hide this)
the swatch has a black, grey and white backing underneath to show multiple alpha effects
startBackgroundColor - (default the last color in color array) the starting color
draggable - (default true (false if no buttonBar)) whether you can drag the component - set to false to not drag
a small grip under the color text shows if draggable
shadowColor - (default rgba(0,0,0,.3)) set to -1 for no drop shadow
shadowBlur - (default 14) the blur of the shadow if shadow is set
buttonBar - (default true unless one row) set to false to hide the button bar with OK and X (close)
circles - (default false) set to true to show colors in circles rather than squares
indicator - (default true) set to false to remove indicator from currentBackgroundColor
backgroundColor - (default black) the color of the background
keyArrows - (default true) set to false to disable keyboard arrows
container - (default frame.zdf) if using show(), hide(), toggle() can set which container to center on
selectedIndex - (default 0) - set the selectedIndex at start
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show() - show the picker (returns the picker for chaining)
hide() - hides the picker
toggle(state - default null) - shows if hidden and hides if showing (returns the picker for chaining)
or pass in true to show picker or false to hide picker
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedColor - gets or sets the selected color swatch
currentValue - same as selectedColor but consistent with other components
currentValueEvent - gets or sets the current value and dispatches a "change" event if set and changed
selectedAlpha - gets or sets the selected alpha (set does not work if alphaPicker is false)
selectedIndex - get or sets the selected index of the colorPicker
colors - read only array of colors in picker - not including greys
greys - read only array of greys in picker if the grey picker is set
toggled - read-only Boolean property as to whether picker is showing
swatch - gets the Rectangle that is the color swatch
swatchBacking - gets the zim Shape that is under the swatch (seen if alpha set low)
swatchText - gets the Label that shows the color text
grip - gets the createjs.Shape for the grip if the panel is dragable
background - gets the Rectangle that is the background (cp.background.color = "white" - now a backgroundColor parameter)
okBut - references the OK Button
closeBut - references the X Button
indicator - gets the zim shape that is the indicator (if indicator is true)
NOTE: alphaPicker is true:
alpaBacking - gets reference to the Rectangle that makes the backing for the alpha slider
alphaBut - the Button on the alpha slider
alphaSlider - the Slider for the alpha
alphaText - the Label for the alpha
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
keyFocus - get or set the keyboard focus on the component - see also zim.KEYFOCUS
will be set to true if this component is the first made or component is the last to be used
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "set" event when a different color or alpha is selected and updated in the picker if the buttonBar is showing
dispatches a "change" event when the OK button is activated and the color or alpha is different than before
or if buttonBar is false dispatches "change" when a new color or alpha is selected
dispatches a "close" event if the OK button is activated and the color has not changed or the X button is pressed
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+67
zim.ColorPicker = function(width, colors, cols, spacing, greyPicker, alphaPicker, startBackgroundColor, draggable, shadowColor, shadowBlur, buttonBar, circles, indicator, backgroundColor, keyArrows, container, selectedIndex, selectedColor, style, group, inherit) {
var sig = "width, colors, cols, spacing, greyPicker, alphaPicker, startBackgroundColor, draggable, shadowColor, shadowBlur, buttonBar, circles, indicator, backgroundColor, keyArrows, container, selectedIndex, selectedColor, style, group, inherit";
var duo; if (duo = zob(zim.ColorPicker, arguments, sig, this)) return duo;
z_d("67");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "ColorPicker";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:500;
if (zot(colors)) colors = DS.colors!=null?DS.colors:null;
if (zot(colors)) standard = true;
if (zot(cols)) cols = DS.cols!=null?DS.cols:10;
if (zot(spacing)) spacing = DS.spacing!=null?DS.spacing:2;
var oneRow = !standard&&colors.length>0&&colors.length<=cols;
if (zot(alphaPicker)) alphaPicker = DS.alphaPicker!=null?DS.alphaPicker:(oneRow?false:true);
if (zot(greyPicker)) greyPicker = DS.greyPicker!=null?DS.greyPicker:(oneRow?false:true);
if (zot(shadowColor)) shadowColor = DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur = DS.shadowBlur!=null?DS.shadowBlur:14;
if (zot(buttonBar)) buttonBar = DS.buttonBar!=null?DS.buttonBar:(oneRow?false:true);
if (zot(draggable)) {
if (buttonBar) {
draggable = DS.draggable!=null?DS.draggable:true;
} else {
draggable = DS.draggable!=null?DS.draggable:false;
}
}
if (zot(circles)) circles = DS.circles!=null?DS.circles:false;
if (zot(indicator)) {
indicator = DS.indicator!=null?DS.indicator:false;
if (!buttonBar) indicator = DS.indicator!=null?DS.indicator:true;
}
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"black";
if (zot(startBackgroundColor)) startBackgroundColor = DS.startBackgroundColor!=null?DS.startBackgroundColor:null;
if (zot(keyArrows)) keyArrows = DS.keyArrows!=null?DS.keyArrows:true;
var that = this;
var stage;
if (zot(container)) {
if (zdf) container = zdf.stage;
else return;
} else if (!container.getBounds) {
return;
} else if (zot(container.getStage)) {
return;
}
that.container = container;
var secondLastBackgroundColor = "#e472c4"; // only used on standard colors
var thirdLastBackgroundColor = "#50c4b7";
var lastAlpha = 1;
var myAlpha = 1;
var box = new createjs.Shape(); // shape that holds all colors and greys
this.addChild(box);
box.x += spacing;
box.y += spacing;
var standard = false;
var colorsTemp; var w;
var greys = [];
if (zot(colors)) {
standard = true;
var num = 6; // six sets 0,3,6,9,C,F - for Web colors
var tot = num*num*num;
num = Math.ceil(Math.pow(tot,1/2));
w = (width - spacing)/18-spacing;
var f = Math.floor(Math.pow(num*num, 1/3));
colorsTemp = [];
for (var i=0; i<6; i++) {
for (var j=0; j<6; j++) {
for (var k=0; k<6; k++) {
colorsTemp.push("#" + con(i*3) + con(j*3) + con(k*3));
}
}
}
colors = []; // flip every six by six sideways and put on two lines
var c, r, nC, nR;
for (i=0; i= 6*3) {f = 1;} else {f = 0;}
nC = c-f*6*3;
nR = r+f*6;
colors[nR*18+nC] = colorsTemp[i];
}
cols = 18;
greys = [thirdLastBackgroundColor, secondLastBackgroundColor];
} else {
w = (width - spacing) / cols - spacing;
}
var rows = Math.ceil(colors.length/cols);
var startAlpha = 1;
var myColor = String(colors[colors.length-1]);
if (!zot(startBackgroundColor)) {
var matches = startBackgroundColor.match(/rgba\((.*)\)/);
if (matches) {
var c = matches[1].split(",");
startAlpha = c.pop();
startBackgroundColor = "rgb("+c.join(",")+")";
}
myColor = String(startBackgroundColor);
}
var lastBackgroundColor;
if (standard) lastBackgroundColor = thirdLastBackgroundColor;
function con(n) {
n = Math.floor(n).toString(16);
return n + "" + n;
}
var g = box.graphics; var f=0; var color, r, c, rX , rY;
var borderColor = DS.borderColor!=null?DS.borderColor:null;
var borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (!zot(borderColor) && zot(borderWidth)) borderWidth = 1;
if (borderWidth && zot(borderColor)) borderColor = "#333";
if (borderWidth) g.s(borderColor).ss(borderWidth);
for (i=0; i 0) background.shadow = new createjs.Shadow(shadowColor, 8, 8, shadowBlur);
function doChange(){
if (myColor != lastBackgroundColor || myAlpha != lastAlpha) {
if (standard && greyPicker) {
thirdLastBackgroundColor = secondLastBackgroundColor;
secondLastBackgroundColor = lastBackgroundColor;
var lastBackgroundColors = [thirdLastBackgroundColor, secondLastBackgroundColor];
for (i=0; i<2; i++) {
var g = box.graphics;
c = Math.floor(i/cols);
r = i%cols;
rX = r*(w+spacing);
rY = c*(w+spacing)+greyHeight;
greys[i] = lastBackgroundColors[i];
g.f(background.color).r(rX-1,rY-1,w+2,w+2).f(lastBackgroundColors[i]).r(rX,rY,w,w);
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
lastBackgroundColor = myColor;
lastAlpha = myAlpha;
that.dispatchEvent("change");
} else {
that.dispatchEvent("close");
}
}
if (draggable) {
var diffX, diffY;
background.on("mousedown", function(e) {
stage = e.target.stage;
diffX = e.stageX/zim.scaX - that.x;
diffY = e.stageY/zim.scaY - that.y;
background.cursor = "move";
});
background.on("pressmove", function(e) {
that.x = e.stageX/zim.scaX-diffX;
that.y = e.stageY/zim.scaY-diffY;
if (that.stage) that.stage.update();
});
background.on("pressup", function(e) {
background.cursor = "default";
if (that.stage) that.stage.update();
});
}
var gridW = cols*(w+spacing);
var gridH = rows*(w+spacing);
if (greyPicker) {
var greyW = greyCols*(w+spacing);
var greyH = greyRows*(w+spacing);
}
box.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", function(e) {
var index = zim.hitTestGrid(box, gridW, gridH, cols, rows, e.stageX, e.stageY, 0, 0, spacing, spacing);
if (!zot(index)) {
myColor = colors[index];
if (buttonBar) {
swatch.color = myColor;
swatchText.text = String(colors[index]).toUpperCase();
if (myColor != lastBackgroundColor) that.dispatchEvent("set");
} else {
doChange();
}
}
if (greyPicker) {
// note greyW not gridW
index = null;
index = zim.hitTestGrid(box, greyW, greyH, greyCols, greyRows, e.stageX, e.stageY, 0, gridH, spacing, spacing);
if (!zot(index)) {
myColor = greys[index];
if (buttonBar) {
swatch.color = myColor;
swatchText.text = greys[index].toUpperCase();
if (myColor != lastBackgroundColor) that.dispatchEvent("set");
} else {
doChange();
}
}
}
if (indicator) positionIndicator(colors.indexOf(myColor));
if (buttonBar) {
if (that.stage) that.stage.update();
} else if (indicator) {
if (that.stage) that.stage.update();
// if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
setAccessibility();
});
Object.defineProperty(this, 'selectedColor', {
get: function() {
return myColor;
},
set: function(value) {
value = value.toLowerCase();
lastBackgroundColor = myColor = value;
if (buttonBar) {
swatch.color = myColor;
swatchText.text = myColor;
if (that.stage) that.stage.update();
}
if (indicator) positionIndicator(colors.indexOf(myColor));
setAccessibility();
}
});
Object.defineProperty(this, 'currentValue', { // alternate to selectedColor
get: function() {
return myColor;
},
set: function(value) {
that.selectedColor = value;
}
});
Object.defineProperty(this, 'currentValueEvent', { // currentValue and also triggers change event
get: function() {
return myColor;
},
set: function(value) {
if (value != that.selectedColor) {
that.selectedColor = value;
that.dispatchEvent("change");
}
}
});
Object.defineProperty(this, 'selectedIndex', {
get: function() {
return colors.indexOf(myColor);
},
set: function(value) {
lastBackgroundColor = myColor = colors[value];
if (buttonBar) {
swatch.color = myColor;
swatchText.text = myColor;
if (that.stage) that.stage.update();
}
if (indicator) positionIndicator(colors.indexOf(myColor));
setAccessibility();
}
});
Object.defineProperty(this, 'selectedAlpha', {
get: function() {
if (alphaPicker) {
return decimals(slider.currentValue);
} else {
return 1;
}
},
set: function(value) {
if (alphaPicker) {
lastAlpha = slider.currentValue = value;
if (swatch) swatch.alpha = lastAlpha;
if (alphaText) alphaText.text = "Alpha: " + decimals(slider.currentValue);
if (that.stage) that.stage.update();
}
}
});
Object.defineProperty(this, 'colors', {
get: function() {
if (greyPicker) return colors.concat(greys);
else return colors;
},
set: function(value) {
if (zon) zogy("ColorPicker() colors is read only - make a new ColorPicker to change");
}
});
if (typeof KEYFOCUS !== typeof undefined) zim.KEYFOCUS = KEYFOCUS;
Object.defineProperty(this, 'keyFocus', {
get: function() {
return zim.KEYFOCUS == that;
},
set: function(value) {
if (zns) zim.KEYFOCUS = that;
else KEYFOCUS = that;
}
});
if (keyArrows && zim.KEYFOCUS) setFocus();
this.on("mousedown", function() {if (keyArrows) setFocus();});
function setFocus() {that.keyFocus = true; var d=document.activeElement; if (d) d.blur();}
function setAccessibility() {
if (that.zimAccessibility) that.zimAccessibility.changeTitle(that, null, true);
}
this.keyDownEvent = function(e) {
if (!that.stage) return;
if ((that.zimAccessibility && that.focus) || (!that.zimAccessibility && that.keyFocus)) {
var currentTemp = that.selectedIndex;
if (e.keyCode == 37 || e.keyCode == 40) {
currentTemp--;
changeMe();
} else if (e.keyCode == 38 || e.keyCode == 39){
currentTemp++;
changeMe();
}
function changeMe() {
if (currentTemp < 0) currentTemp = that.colors.length-1;
if (currentTemp > that.colors.length-1) currentTemp = 0;
that.selectedIndex = currentTemp;
that.dispatchEvent("change");
if (that.stage) that.stage.update();
}
}
};
window.addEventListener("keydown", this.keyDownEvent);
this.hide = function() {
that.removeFrom();
that.toggled = false;
if (that.zimAccessibility) {
var a = that.zimAccessibility;
a.resize(that);
if (accessibilityClicker) accessibilityClicker.focus();
else that.zimTabTag.nextSibling.focus();
setTimeout(function() {a.talk("ColorPicker has been closed.");}, 50);
}
return that;
};
var accessibilityClicker;
this.show = function() {
that.center(that.container);
if (that.zimAccessibility) {
var a = that.zimAccessibility;
setTimeout(function(){if (a.activatedObject) accessibilityClicker = a.activatedObject.zimTabTag;}, 50);
a.resize(that);
a.tabIndex = that.zimTabIndex;
}
that.toggled = true;
return that;
};
this.toggle = function(state) {
if (state===true) that.show();
else if (state===false) that.hide();
else if (that.container.contains(that)) that.hide();
else that.show();
return that;
};
function decimals(n) {
return Math.round(n*Math.pow(10, 2))/Math.pow(10, 2);
}
if (zot(selectedIndex)) selectedIndex=DS.selectedIndex!=null?DS.selectedIndex:0;
that.selectedIndex = selectedIndex;
if (zot(selectedColor)) selectedColor=DS.selectedColor!=null?DS.selectedColor:null;
if (selectedColor!=null) that.selectedColor = selectedColor;
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.ColorPicker(width, standard?null:colors, cols, spacing, greyPicker, alphaPicker, startBackgroundColor, draggable, shadowColor, shadowBlur, buttonBar, circles, indicator, backgroundColor, keyArrows, container, selectedIndex, selectedColor, style, this.group, inherit));
};
this.dispose = function(a,b,disposing) {
window.removeEventListener("keydown", that.keyDownEvent);
if (slider) slider.dispose();
if (!disposing) this.zimContainer_dispose(true);
return true;
};
};
zim.extend(zim.ColorPicker, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-67
//
/*--
zim.TextEditor = function(width, color, backgroundColor, fieldColor, fieldHeight, textSize, sizeList, optionList, colorList, fontList, live, button, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, wrap, limit, scroll, placeholder, password, borderColor, borderWidth, margin, corner, shadowColor, shadowBlur, draggable, boundary, frame, fontListHeight, fontListViewNum, style, group, inherit)
TextEditor
zim class - extends a zim.Panel which extends a zim.Container which extends a createjs.Container
DESCRIPTION
A configurable text editor for a ZIM Label - or text in code memory.
Call the editor.show(label) method and pass in the label - it will let the user change the following properties:
text, color, bold, italic, align, size, and font
Which ones the editor uses can be set with parameters.
SEE: https://zimjs.com/cat/texteditor.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var label = new Label({
text:"press to edit with TextEditor",
italic:true,
align:CENTER,
font:"verdana"
}).center().expand().tap(function () {
textEditor.show(label);
});
var textEditor = new TextEditor({
colorList:true, // or array of colors
optionList:["bold","italic","align"], // or true, or array with any of these
sizeList:true, // or array of sizes
fontList:true, // or array of fonts
live:true, // default
scroll:true // default, etc.
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
The TextEditor is made of of the following sub components
and many styles need to be set on the sub component types:
Panel, TextArea, Button, ColorPicker, Selector, Stepper, List
For instance STYLE = {type:{Panel:{titleBarBackgroundColor:red}}}
width - (default 400) the width of the editor
color - (dark) the color of the TextArea text in the editor
backgroundColor - (default lighter) the background color of the editor
fieldColor - (default backgroundColor darkened .05) - the background color of the TextArea
fieldHeight - (default button height plus 2 margins) - the height of the TextArea
textSize - (default 20) the size of the text in the TextArea
sizeList - (default false) set to true to show numbers from 5-500
or set to an array of numbers used for the size Stepper [10,12,14,16] for instance
optionList - (default false) set to true to show ["bold", "italic", "align"]
or set to an array with any of these values ["bold", "italic"] for instance
colorList - (default false) set to true to show the default ZIM ColorPicker
or set to an array with colors [red, green, blue, black, "violet", "#333"] for instance
fontList - (default false) set to true to show a default list of fonts
"Arial",
"Courier New",
"Georgia",
"Helvetica",
"Palatino",
"Tahoma",
"Verdana",
// plus on desktop:
"Impact",
"Comic Sans"
or set to an array with desired fonts ["courier", "verdana"] for instance
live - (default true) will update the label as the text is typed
set to false to update only on button press - note, other setting update live regardless
button - (default green check) set to a custom ZIM Button if desired
titleBar - (default "Text Editor") a String or ZIM Label title for the panel that will be presented on a titleBar across the top
titleBarColor - (default "black") the text color of the titleBar if a titleBar is requested
titleBarBackgroundColor - (default "rgba(0,0,0,.2)") the background color of the titleBar if a titleBar is requested
titleBarHeight - (default fit label) the height of the titleBar if a titleBar is requested
wrap - (default true) set to false to not wrap text in TextArea (wrapping on the actual label can be done with label.lineWidth)
limit - (default null) set to a number to limit the TextArea number of characters
scroll - (default true) set to false to not show a vertical scrollbar when needed - note if textHeight is not high enough, a scrollbar may not show
placeholder - (default null) set to true to show default text - will be overwritten with label text if there is text
password - (default false) set to true to make the TextArea a password field - shows dots - the label will not show dots
borderColor - (default #888) border color
borderWidth - (default 1) the thickness of the border
margin - (default 10) the margin around the various sub components
corner - (default 0) the round of corner
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
shadowColor - (default "rgba(0,0,0,.3)" if shadowBlur) the shadow color - set to -1 for no shadow
shadowBlur - (default 14 if shadowColor) the shadow blur - set to -1 for no shadow
draggable - (default true if titleBar) set to false to not allow dragging titleBar to drag window
boundary - (default null) set to ZIM Boundary() object - or CreateJS.rectangle()
frame - (default zdf - ZIM Default Frame) pass in a frame if not the default frame - lets TextArea and ColorPicker work
fontListHeight - (default 100) the height of the font list if there is one
fontListViewNum - (default 3) the number of fonts to show in the font list if there is one
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show(label, x, y, frame) - show the editor and pass in the label to operate on
the editor will appear centered above or below the text depending on where there is more room
this can be overridden with the x and y parameters
the TextEditor will show on the stage of the Label
if the label is not on the stage then the stage of the frame parameter otherwise the stage of the ZIMDefaultFrame
If the editor is already open it will not move
Calling show(label2) on a different label will switch the editor to that label
see also the label property
hide() - hides the editor
closeColorPicker() - close the ColorPicker - this needs to display the text (which is hidden when the ColorPicker opens)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: see all the methods of the ZIM Panel
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
textArea - reference to the TextArea
label - get or set the label associated with the textEditor
button - reference to the Button
if various features are set:
swatch - reference to the Rectangle showing color
colorPicker - reference to the ColorPicker
bold - reference to the bold Button
italic - reference to the italic Button
align - reference to the align Selector
size - reference to the size Stepper
font - reference to the font List
ALSO: see all the properties of the ZIM Panel including close, titleBar, etc.
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches an "input" event when the text is changed - although default is to update live
dispatches an "update" event when any property is changed and where text is changed
dispatches a "set" event when button is pressed
dispatches a "close" event when closed
dispatches a "color" event when ColorPicker is opened
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+67.1
zim.TextEditor = function(width, color, backgroundColor, fieldColor, fieldHeight, textSize, sizeList, optionList, colorList, fontList, live, button, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, wrap, limit, scroll, placeholder, password, borderColor, borderWidth, margin, corner, shadowColor, shadowBlur, draggable, boundary, frame, fontListHeight, fontListViewNum, style, group, inherit) {
var sig = "width, color, backgroundColor, fieldColor, fieldHeight, textSize, sizeList, optionList, colorList, fontList, live, button, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, wrap, limit, scroll, placeholder, password, borderColor, borderWidth, margin, corner, shadowColor, shadowBlur, draggable, boundary, frame, fontListHeight, fontListViewNum, style, group, inherit";
var duo; if (duo = zob(zim.TextEditor, arguments, sig, this)) return duo;
z_d("67.1");
this.group = group;
var DS = style===false?{}:zim.getStyle("TextEditor", this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:400;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:zim.lighter;
if (zot(titleBar)) titleBar = DS.titleBar!=null?DS.titleBar:"Text Editor";
if (zot(draggable)) draggable = DS.draggable!=null?DS.draggable:true;
if (zot(titleBarHeight)) titleBarHeight = DS.titleBarHeight!=null?DS.titleBarHeight:30;
if (zot(fieldColor)) fieldColor = DS.fieldColor!=null?DS.fieldColor:backgroundColor.darken(.05);
if (zot(live)) live = DS.live!=null?DS.live:true;
if (zot(wrap)) wrap = DS.wrap!=null?DS.wrap:true;
if (zot(scroll)) scroll = DS.scroll!=null?DS.scroll:true;
if (zot(margin)) margin = DS.margin!=null?DS.margin:10;
if (zot(limit)) limit = DS.limit!=null?DS.limit:null;
if (zot(titleBar)) titleBar = DS.titleBar!=null?DS.titleBar:null;
if (zot(sizeList)) sizeList = DS.sizeList!=null?DS.sizeList:null;
if (zot(colorList)) colorList = DS.colorList!=null?DS.colorList:null;
if (zot(optionList)) optionList = DS.optionList!=null?DS.optionList:null;
if (zot(fontList)) fontList = DS.fontList!=null?DS.fontList:null;
if (zot(fieldColor)) fieldColor = DS.fieldColor!=null?DS.fieldColor:null;
if (zot(fieldHeight)) fieldHeight = DS.fieldHeight!=null?DS.fieldHeight:null;
if (zot(textSize)) textSize = DS.textSize!=null?DS.textSize:null;
if (zot(fontListHeight)) fontListHeight = DS.fontListHeight!=null?DS.fontListHeight:100;
if (zot(fontListViewNum)) fontListViewNum = DS.fontListViewNum!=null?DS.fontListViewNum:3;
if (zot(frame)) {
if (zdf) {
frame = zdf;
} else {
if (zon) {zog("zim.TextEditor - please provide a reference to zim Frame");} return;
}
}
this.zimPanel_constructor(width, 300, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, backgroundColor, borderColor, borderWidth, corner, true, null, null, null, shadowColor, shadowBlur, draggable, boundary, null, style, group, inherit);
var that = this;
if (zot(button)) button = new zim.Button({
width:50,height:50,
// label:new zim.Label({text:"✓", bold:true, color: zim.white}),
label:"",
icon:new Shape().sca(.4).f("white").p("AikFsQg5jmhphxIA1gXQBeBGA3CwQC8mRCpjOIBfAoQkPFGiSFpg"),
color:zim.white,
corner:10,
backgroundColor:zim.green.darken(.2),
borderColor:zim.white,
borderWidth:2,
rollBackgroundColor:zim.green,
shadowBlur:3
})
.pos(margin, titleBarHeight+margin*2, zim.RIGHT, zim.TOP, that);
that.button = button;
button.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", submit);
if (zot(fieldHeight)) fieldHeight = DS.fieldHeight!=null?DS.fieldHeight:button.height+margin*2;
function submit() {
if (!live) label.text = textArea.text;
that.hide();
that.dispatchEvent("set");
}
var textArea = that.textArea = new zim.TextArea({
color:color,
backgroundColor:fieldColor,
width:width-button.width-margin*3,
height:zot(fieldHeight)?button.height+margin*2:fieldHeight,
expand:10,
password:password,
placeholder:placeholder,
frame:frame
}).loc(margin,titleBarHeight+margin+(fieldHeight&&fieldHeight<(button.height+margin*2)?(button.height-fieldHeight)/2+margin:0),null,null,false);
if (!wrap) textArea.tag.style.whiteSpace = "nowrap";
if (limit) textArea.tag.setAttribute("maxLength", limit);
if (scroll) textArea.tag.style.overflowY = "auto";
var label = new zim.Label(); // surrugate label
that.on("pressmove", function () {
textArea.resize();
});
that.on("close", function () {
if (that.inputEvent) textArea.off("input", that.inputEvent);
textArea.removeFrom();
});
that.panelHeight = titleBarHeight+margin+Math.max(fieldHeight, button.height+margin*2) + margin;
var mob = zim.mobile();
var baseSize = mob?35:30;
if (sizeList || optionList || colorList) {
new zim.Rectangle(width,baseSize+margin,"rgba(0,0,0,.05)").loc(0, that.panelHeight, that);
var extras = [];
if (colorList) {
var arr = Array.isArray(colorList);
var colorPicker = that.colorPicker = new zim.ColorPicker({
colors:arr?colorList:null,
cols:arr?Math.min(colorList.length,12):null,
alphaPicker:false,
greyPicker:!arr,
container:frame.stage
});
colorPicker.on("close",closePicker);
function closePicker() {
textArea.tag.style.display = "block";
colorPicker.hide();
if (that.stage) that.stage.update();
}
colorPicker.on("change", function () {
label.color = color.color = colorPicker.selectedColor;
that.dispatchEvent("update");
closePicker();
});
that.closeColorPicker = function() {closePicker();}
var color = that.swatch = new zim.Rectangle(baseSize,baseSize,label.color,zim.dark,1).cur();
color.on("mousedown",function () {
that.dispatchEvent("color");
textArea.tag.style.display = "none";
colorPicker.selectedColor = color.color;
colorPicker.show();
if (that.stage) that.stage.update();
});
extras.push(color);
}
if (optionList) {
if (optionList === true) optionList = ["bold", "italic", "align"];
if (zot(STYLE)) STYLE = {};
if (zot(STYLE.group)) STYLE.group = {};
STYLE.group.zimEditor = {
width:baseSize,
height:baseSize,
corner:0,
borderColor:zim.tin,
shadowBlur:-1,
backgroundColor:zim.light,
rollBackgroundColor:zim.light,
toggleBackgroundColor:zim.green,
toggleColor:zim.grey
};
var bold, italic, selector;
zim.loop(optionList, function (option) {
if (option.toLowerCase()=="bold") {
bold = that.bold = new zim.Button({
label:new zim.Label({text:"B", color:zim.grey, size:16, bold:true}),
toggle:"B",
group:"zimEditor"
});
bold.on("click", function () {
label.bold = bold.toggled;
that.dispatchEvent("update");
if (that.stage) that.stage.update();
});
extras.push(bold);
if (label.bold) bold.toggle();
} else if (option.toLowerCase()=="italic") {
italic = that.italic = new zim.Button({
label:new zim.Label({text:"I", color:zim.grey, size:16, bold:true, italic:true}),
toggle:"I",
group:"zimEditor"
});
italic.on("click", function () {
label.italic = italic.toggled;
that.dispatchEvent("update");
if (that.stage) that.stage.update();
});
extras.push(italic);
if (label.italic) italic.toggle();
} else if (option.toLowerCase()=="align") {
var alignOptions = new zim.Tile(new zim.Rectangle(baseSize-10,baseSize-10, zim.grey).centerReg(), 3, 1, 10, 10);
var icons = mob?["⇚","⇔","⇛"]:["⇐","⇔","⇒"];
zim.loop(3, function (i) {
var r = alignOptions.getChildAt(i);
new zim.Label(icons[i], baseSize*2/3, null, zim.white).center(r).expand(10);
// rectangles not expanding? last label not expanding?
});
var i = 0;
if (label.align == "right") i = 2;
else if (label.align == "center" || label.align == "middle") i = 1;
selector = that.align = new zim.Selector({
tile:alignOptions,
corner:0,
borderWidth:1,
borderColor:zim.grey,
backgroundColor:zim.clear,
selectedIndex:i
});
selector.on("change", function () {
if (selector.selectedIndex == 0) label.align = "left";
else if (selector.selectedIndex == 1) label.align = "center";
if (selector.selectedIndex == 2) label.align = "right";
that.dispatchEvent("update");
if (that.stage) that.stage.update();
});
extras.push(selector);
}
});
delete STYLE.group.zimEditor;
}
if (sizeList) {
var size = that.sizePicker = new zim.Stepper({
list:sizeList===true?null:sizeList,
stepperType:sizeList===true?null:"list",
min:sizeList===true?5:null,
max:sizeList===true?500:null,
width:150,
shadowBlur:-1,
borderColor:zim.dark,
borderWidth:2,
corner:0,
backgroundColor:zim.green,
downForward:false
}).siz(null,baseSize);
size.arrowPrev.expand(0);
size.textBox.color = zim.lighter;
size.on("change", function () {
label.size = size.currentValue;
that.dispatchEvent("update");
if (that.stage) that.stage.update();
});
size.currentValue = label.size;
extras.push(size);
}
var tile = new zim.Tile(extras, extras.length, 1, 10, 10, true)
.loc(margin, that.panelHeight+margin/2, that);
that.panelHeight = that.panelHeight + margin + tile.height + margin;
}
var fonts;
if (fontList) {
if (!Array.isArray(fontList)) {
fonts = [
"Arial",
"Courier New",
"Georgia",
"Helvetica",
"Palatino",
"Tahoma",
"Verdana"
];
if (!mob) {
fonts = fonts.concat([
"Comic Sans MS",
"Impact"
]);
}
fonts.sort();
} else {
fonts = fontList;
}
var font = that.fonts = new zim.List({
width:width-margin*2,
height:fontListHeight,
viewNum:fontListViewNum,
backgroundColor:zim.moon,
color:zim.grey,
rollColor:zim.dark,
rollBackgroundColor:zim.green.lighten(.5),
selectedBackgroundColor:zim.mist,
selectedRollBackgroundColor:zim.green.lighten(.6),
selectedColor:zim.dark,
backdropColor:zim.light,
scrollBarColor:zim.dark,
shadowBlur:-1,
list:fonts
}).center(that).loc(null, that.panelHeight);
font.on("change",function () {
label.font = font.currentValue;
that.dispatchEvent("update");
if (that.stage) that.stage.update();
});
that.panelHeight = that.panelHeight + margin + font.height + margin;
}
that.show = function(l, x, y, frame) {
if (that.parent) {
if (l==that.label) return that;
that.label = l;
return that;
}
label = l;
textArea.addTo(that);
var stage;
if (label && label.stage) stage = label.stage;
else if (frame) stage = frame.stage;
else if (zdf) stage = zdf.stage;
else return that;
if (!zot(x) || !zot(y)) that.loc(x,y);
else if (label && label.y>stage.height/2) that.loc(stage.width/2-width/2, label.y-that.panelHeight-stage.height*.05, stage);
else if (label && label.y<=stage.height/2) that.loc(stage.width/2-width/2, label.y+label.height+stage.height*.05, stage);
else that.center(stage);
if (that.y < 20) that.y = 20;
if (that.y+that.height > that.stage.height) that.y = that.stage.height-that.height-20;
setLabel();
that.stage.update();
return that;
};
function setLabel() {
// set all the defaults for the label
if (label) textArea.text = label.text;
if (color) color.color = label.color;
if (bold) bold.toggle(label.bold==true);
if (italic) italic.toggle(label.italic==true);
if (selector) {
selector.noAnimate = true;
if (label.align == "center") selector.selectedIndex = 1;
else if (label.align == "right") selector.selectedIndex = 2;
else selector.selectedIndex = 0;
}
if (size) size.currentValue = label.size;
if (font) font.currentValue = label.font;
if (that.inputEvent) textArea.off("input", that.inputEvent);
that.inputEvent = textArea.on("input", function (e) {
if (live) label.text = textArea.text;
that.dispatchEvent("input");
that.dispatchEvent("update");
if (that.stage) that.stage.update();
});
}
that.hide = function () {
if (colorList) colorPicker.hide();
if (textArea) textArea.removeFrom();
if (zot(that.stage)) return;
var stage = that.stage;
that.removeFrom();
stage.update();
return that;
};
Object.defineProperty(that, 'label', {
get: function() {
return label;
},
set: function(value) {
label = value;
setLabel();
}
});
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.TextEditor(width, color, backgroundColor, fieldColor, fieldHeight, textSize, sizeList, optionList, colorList, fontList, live, button, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, wrap, limit, scroll, placeholder, password, borderColor, borderWidth, margin, corner, shadowColor, shadowBlur, draggable, boundary, frame, fontListHeight, fontListViewNum, style, this.group, inherit));
};
this.dispose = function(a,b,disposing) {
var stage = that.stage;
if (that.inputEvent) textArea.off("input", that.inputEvent);
if (colorPicker) colorPicker.dispose();
if (color) color.dispose();
if (font) font.dispose();
if (button) button.dispose();
if (textArea) textArea.dispose();
if (selector) selector.dispose();
if (bold) bold.dispose();
if (italic) italic.dispose();
if (size) size.dispose();
if (!disposing) this.zimPanel_dispose();
if (that.stage) that.stage.update();
that.textArea = that.color = that.colorPicker = that.font = that.button = that.selector = that.bold = that.italic = that.size = null;
return true;
};
};
zim.extend(zim.TextEditor, zim.Panel, ["clone", "dispose"], "zimPanel", false);
//-67.1
/*--
zim.Keyboard = function(labels, backgroundColor, color, shiftBackgroundColor, shiftHoldBackgroundColor, placeBackgroundColor, placeColor, cursorColor, shadeAlpha, borderColor, borderWidth, margin, corner, draggable, placeClose, shadowColor, shadowBlur, container, data, place, special, rtl, hardKeyboard, layout, style, group, inherit)
Keyboard
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
The Keyboard class makes a keyboard ideal for mobile or touch screens.
Often, it seems the mobile keyboard can cause problems with layout.
This in-canvas keyboard requires much less testing and concern.
The Keyboard can work with ZIM Labels to give input text without a TextArea.
Thanks Frank Los for the initial design and coding of the Keyboard.
Keyboard also captures hard keyboard keydown and will type that as well
See https://zimjs.com/keyboard
NOTE: press and hold down the vowels for multiple vowel options
NOTE: currently, multi-line Label input is not supported
NOTE: the width of the Label can be set by the Label's lineWidth paremeter
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// create Labels to capture the text from the keyboard
var text1 = new Label({text:"", backgroundColor:white}).pos(100,100);
var text2 = new Label({text:"", backgroundColor:white}).pos(100,200);
// create a new Keyboard and pass in the labels as an array
// or if just one label, then pass in the label
var keyboard = new Keyboard([text1, text2]);
// if just the letter is needed use the keydown event
keyboard.on("keydown", function(e) {
zog(e.letter);
});
// create events to capture a mousedown on the labels
var text1Event = text1.on("mousedown", activate);
var text2Event = text2.on("mousedown", activate);
function activate(e) {
keyboard.show();
// remove the events when keyboard is active
text1.off("mousedown", text1Event);
text2.off("mousedown", text2Event);
}
keyboard.show(); // optionally show the keyboard to start
// add back the events to show the keyboard
keyboard.on("close", function() {
text1.on("mousedown", text1Event);
text2.on("mousedown", text2Event);
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
labels - (default null) a ZIM Label to show letters in or an array of labels
Keyboard will add a cursor to the Labels
and provide management across multiple labels
currently, multiline labels are not supported
setting the label lineWidth will set the max width of the label
backgroundColor - (default "#333") an css color for the background color of the keys
color - (default "white") the color of the text
shiftBackgroundColor - (default "orange") the color of the active shift key
shiftHoldBackgroundColor - (default "red") the color of the active shift hold key
placeBackgroundColor - (default "50c4b7") the color of the arrow backings when placing cursor in label
placeColor - (default "50c4b7") the color of the arrow text when placing cursor in label
cursorColor - (default "50c4b7") the cursor color
shadeAlpha - (default .2) special keys are shaded darker by this alpha
margin - (default 5) the margin around the keyboard from the container width
corner - (default 30) the round of the corner (set to 0 for no corner)
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
draggable - (default false) set to true to show the drag handle at top right
placeClose - (default true) shows an x key to close the cursor placement menu
shadowColor - (default "rgba(0,0,0,.2)") set to -1 for no shadow
shadowBlur - (default 14) how blurred the shadow is if the shadow is set
container - (default zimCurrentFrame stage) if placing Keyboard in different container or stage
data - (default see below) pass in data for the letters on the three sets of keyboards
also see the layout parameter for current default layouts like "arabic", "hebrew", etc.
Below is the default data - change any of the keys to change keyboard
There must be three boards (you can request more)
There must be a button specified on the fourth row to toggle to the second screen and back
There must be a button on the second and third screen at the start of the third row
to toggle between the second and third screen
The "shift" and "delete" keys are optional and can be moved or removed
There is a "back" key that is like the "backspace" key but takes the space of one key and not two keys
There will be at least 10 key places but there can be more than 10 keys per row
The last element of the outer array is a an object with special characters for e,u,i,o,a,n
If left off then it will use the characters below in the example.
These can be changed to any characters showing an extra set of any characters.
The fifth and sixth elements are lowercase to uppercase and uppercase to lowercase override mappings
For instance, in the turkish layout ı:"I" and i:"İ" for lowercase to uppercase
and I:"ı" and İ:"i" for uppercase to lowercase.
Use the data property to get this array if desired:
var data = [
[
["q","w","e","r","t","y","u","i","o","p"],
["a","s","d","f","g","h","j","k","l"],
["shift","z","x","c","v","b","n","m","backspace"],
["?123"] // rest of bottom line automatically added
],[
["1","2","3","4","5","6","7","8","9","0"],
["!","@","#","$","/","^","&","*","(",")"],
["1/2","-","'", "\"",":",";",",","?","backspace"],
["ABC"] // rest of bottom line automatically added
],[
["+","x","%","=","<",">","{","}","[","]"],
["€","£","¥", "$", "₩", "~", "`","¤","♡","☆"],
["2/2","_","\\","|","《","》","¡","¿","backspace"],
["ABC"] // rest of bottom line automatically added
],{
e:["ė","ē","ę","ê","é","ë","è"],
u:["ū","û","ú","ü","ù"],
i:["ī","į","ì","í","ï","î"],
o:["ō","œ","ø","õ","ô","ó","ö","ò"],
a:["ā","ã","å","â","á","ä","à","æ"],
n:["ñ","ń"]
},{
lowercaseletter:"uppercaseletter", // override lowercase to uppercase map
lc2:"uc2"
},{
uppercaseletter:"lowercaseletter", // override uppercase to lowercase map
uc2:"lc2"
}
];
place (default true) - set to false to not add place arrows when selecting Label
special (default null) - set to a string to add a special key to the left of the space bar
rtl (default false) - (Experimental) set to true to use right-to-left text
hardKeyboard (default true) - set to false to not include keypresses from physical keyboard
layout (default "qwerty") - set to change the layout (also see data parameter for custom layout)
additionally supported layouts are "azerty", "hebrew", "turkish", "arabic" - thanks to those who submitted layouts!
please let us know at https://zimjs.com/slack if you are using a layout that others would use!
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show(index) - shows the Keyboard - use this rather than addTo(), etc.
index (default null) specify the index of the labels array to show cursor in
hide() - hides the keyboard
toggle(state - default null) - shows if hidden and hides if showing (returns the keyboard for chaining)
or pass in true to show keyboard or false to hide keyboard
addChar(char) - add a character to the currentLabel at the currentIndex
removeChar() - removes the chararcter in the currentLabel at the currentIndex-1 (a backspace)
addLabels(labels) - add a ZIM Label or an array of Labels to the labels list for the Keyboard
removeLabels(labels) - remove a ZIM Label or an array of Labels
showPlace() - show the place menu for cursor
hidePlace() - hide the place menu for cursor
resize() - scales the keyboard to the stage with margin and places at bottom of screen
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a clone of the Keyboard
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
data - get the data array for the keyboard - see the data parameter for details and to set value for data
labels - get the labels array - use addLabels() and removeLabels() to set
selectedLabel - the label with the cursor or -1 if no cursor
selectedIndex - the index of the cursor in the selected label or -1 if no cursor
type - holds the class name as a String
toggled - read-only Boolean that is true if keyboard is visible and false if not
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
Dispatches a "keydown" event with an event object having a letter property
keyboard.on("keydown", function(e) {zog(e.letter);}); // logs letter pressed or "del" for delete
Dispatches a "special" event if the special parameter is used and the special key is pressed
Dispatches a "close" event when close keyboard icon at bottom right is pressed
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+67.2
zim.Keyboard = function(labels, backgroundColor, color, shiftBackgroundColor, shiftHoldBackgroundColor, placeBackgroundColor, placeColor, cursorColor, shadeAlpha, borderColor, borderWidth, margin, corner, draggable, placeClose, shadowColor, shadowBlur, container, data, place, special, rtl, hardKeyboard, layout, style, group, inherit) {
var sig = "labels, backgroundColor, color, shiftBackgroundColor, shiftHoldBackgroundColor, placeBackgroundColor, placeColor, cursorColor, shadeAlpha, borderColor, borderWidth, margin, corner, draggable, placeClose, shadowColor, shadowBlur, container, data, place, special, rtl, hardKeyboard, layout, style, group, inherit";
var duo; if (duo = zob(zim.Keyboard, arguments, sig, this)) return duo;
z_d("67.2");
this.zimContainer_constructor(1000,400,null,null,false);
this.type = "Keyboard";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(labels)) labels = DS.labels!=null?DS.labels:[];
if (!Array.isArray(labels)) labels = [labels];
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#333";
if (zot(color)) color = DS.color!=null?DS.color:"white";
if (zot(shiftBackgroundColor)) shiftBackgroundColor = DS.shiftBackgroundColor!=null?DS.shiftBackgroundColor:"orange";
if (zot(shiftHoldBackgroundColor)) shiftHoldBackgroundColor = DS.shiftHoldBackgroundColor!=null?DS.shiftHoldBackgroundColor:"red";
if (zot(placeBackgroundColor)) placeBackgroundColor = DS.placeBackgroundColor!=null?DS.placeBackgroundColor:"#50c4b7";
if (zot(placeColor)) placeColor = DS.placeColor!=null?DS.placeColor:color;
if (zot(cursorColor)) cursorColor = DS.cursorColor!=null?DS.cursorColor:"#50c4b7";
if (zot(shadeAlpha)) shadeAlpha = DS.shadeAlpha!=null?DS.shadeAlpha:.2;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"rgba(0,0,0,.1)";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(margin)) margin = DS.margin!=null?DS.margin:5;
if (zot(corner)) corner = DS.corner!=null?DS.corner:30;
if (zot(draggable)) draggable = DS.draggable!=null?DS.draggable:false;
if (zot(placeClose)) placeClose = DS.placeClose!=null?DS.placeClose:true;
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.2)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:14;
if (zot(data)) data = DS.data!=null?DS.data:[
[
["q","w","e","r","t","y","u","i","o","p"],
["a","s","d","f","g","h","j","k","l"],
["shift","z","x","c","v","b","n","m","backspace"],
["?123"] // rest of bottom line automatically added
],[
["1","2","3","4","5","6","7","8","9","0"],
["!","@","#","$","/","^","&","*","(",")"],
["1/2","-","'", "\"",":",";",",","?","backspace"],
["ABC"] // rest of bottom line automatically added
],[
["+","x","%","=","<",">","{","}","[","]"],
["€","£","¥", "$", "₩", "~", "`","¤","♡","☆"],
["2/2","_","\\","|","《","》","¡","¿","backspace"],
["ABC"] // rest of bottom line automatically added
]
];
if (!data[3]) data[3] = {
e:["ė","ē","ę","ê","é","ë","è"],
u:["ū","û","ú","ü","ù"],
i:["ī","į","ì","í","ï","î"],
o:["ō","œ","ø","õ","ô","ó","ö","ò"],
a:["ā","ã","å","â","á","ä","à","æ"],
n:["ñ","ń"]
};
var that = this;
if (zot(place)) place = DS.place!=null?DS.place:true;
if (zot(rtl)) rtl = DS.rtl!=null?DS.rtl:false;
if (zot(hardKeyboard)) hardKeyboard = DS.hardKeyboard!=null?DS.hardKeyboard:true;
if (zot(layout)) layout = DS.layout!=null?DS.layout:"qwerty";
layout = layout.toLowerCase();
if (layout != "qwerty") {
if (layout == "arabic") {
data = [
[
["ض", "ص", "ث", "ق", "ف", "غ", "ع", "ه", "خ", "ح", "ج"],
["ش", "س", "ي", "ب", "ل", "ا", "ت", "ن", "م", "ك", "ط"],
["ذ", "ء", "ؤ", "ر", "ى", "ة", "و", "ز", "ظ", "د","back"],
["?123","ـ"] // rest of bottom line automatically added
],[
["1","2","3","4","5","6","7","8","9","0","*"],
["!","@","#","$","/","^","&","*","(",")","*"],
["1/2","-","'", "\"",":",";",",","?","*","backspace"],
["ABC","*"] // rest of bottom line automatically added
],[
["+","x","%","=","<",">","{","}","[","]","*"],
["€","£","¥", "$", "₩", "~", "`","¤","♡","☆","*"],
["2/2","_","\\","|","《","》","¡","¿","*","backspace"],
["ABC","*"] // rest of bottom line automatically added
],{
ا:["أ","إ","آ","ء"],
ى:["ئ"],
ء:["ئ","ؤ"],
و:["ؤ"],
ـ:["ٍ", "ً", "ٌ", "ْ", "ُ", "ِ", "َ", "ّ"],
"*":["ٍ", "ً", "ٌ", "ْ", "ُ", "ِ", "َ", "ّ"],
n:["ñ","ń"]
}
];
} else if (layout == "hebrew") {
data = [
[
["ק", "ר", "א", "ט", "ו", "ן", "ם", "פ", "backspace"],
["ש", "ד", "ג", "כ", "ע", "י", "ח", "ל", "ך", "ף"],
["ז", "ס", "ב", "נ", "ה", "מ", "צ", "ת", "ץ"],
["?123", ","] // rest of bottom line automatically added
], [
["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"],
["!", "@", "#", "$", "/", "^", "&", "*", "(", ")"],
["1/2", "-", "'", "\"", ":", ";", ",", "?", "backspace"],
["ABC", ","] // rest of bottom line automatically added
], [
["+", "x", "%", "=", "<", ">", "{", "}", "[", "]"],
["€", "£", "¥", "$", "₩", "~", "`", "¤", "♡", "☆"],
["2/2", "_", "\\", "|", "《", "》", "¡", "¿", "backspace"],
["ABC", ","] // rest of bottom line automatically added
], {
e: ["ė", "ē", "ę", "ê", "é", "ë", "è"],
u: ["ū", "û", "ú", "ü", "ù"],
i: ["ī", "į", "ì", "í", "ï", "î"],
o: ["ō", "œ", "ø", "õ", "ô", "ó", "ö", "ò"],
a: ["ā", "ã", "å", "â", "á", "ä", "à", "æ"],
n: ["ñ", "ń"]
}
];
} else if (layout == "azerty") {
data = [
[
["a","z","e","r","t","y","u","i","o","p"],
["q","s","d","f","g","h","j","k","l","m"],
["shift","w","x","c","v","b","n","´","backspace"],
["?123",","] // rest of bottom line automatically added
],[
["1","2","3","4","5","6","7","8","9","0"],
["!","@","#","$","/","^","&","*","(",")"],
["1/2","-","'", "\"",":",";",",","?","backspace"],
["ABC",","] // rest of bottom line automatically added
],[
["+","x","%","=","<",">","{","}","[","]"],
["€","£","¥", "$", "₩", "~", "`","¤","♡","☆"],
["2/2","_","\\","|","《","》","¡","¿","backspace"],
["ABC",","] // rest of bottom line automatically added
],{
e:["ė","ē","ę","ê","é","ë","è"],
u:["ū","û","ú","ü","ù"],
i:["ī","į","ì","í","ï","î"],
o:["ō","œ","ø","õ","ô","ó","ö","ò"],
a:["ā","ã","å","â","á","ä","à","æ"],
n:["ñ","ń"]
}
];
} else if (layout == "turkish") {
data = [
[
["q","w","e","r","t","y","u","ı","o","p","ğ","ü"],
["a","s","d","f","g","h","j","k","l","ş","i"],
["shift","z","x","c","v","b","n","m","ö","ç","backspace"],
["?123","*"] // rest of bottom line automatically added
],[
["1","2","3","4","5","6","7","8","9","0","*"],
["!","@","#","$","/","^","&","*","(",")","*"],
["1/2","-","'", "\"",":",";",",","?","*","backspace"],
["ABC","*"] // rest of bottom line automatically added
],[
["+","x","%","=","<",">","{","}","[","]","*"],
["€","£","¥", "$", "₩", "~", "`","¤","♡","☆","*"],
["2/2","_","\\","|","《","》","¡","¿","*","backspace"],
["ABC","*"] // rest of bottom line automatically added
],{
e:["ė","ē","ę","ê","é","ë","è"],
u:["ū","û","ú","ü","ù"],
i:["ī","į","ì","í","ï","î"],
o:["ō","œ","ø","õ","ô","ó","ö","ò"],
a:["ā","ã","å","â","á","ä","à","æ"],
n:["ñ","ń"]
},{
ı:"I", // lowercase to uppercase map
i:"İ"
},{
I:"ı", // uppercase to lowercase map
İ:"i"
}
];
}
}
that.data = data;
var mess = "zim display - Keyboard(): Please pass in a reference to a container with bounds set";
if (zot(container)) {
if (zdf) {
container = zdf.stage;
} else {
zogy(mess);
return;
}
} else if (!container.getBounds) {
zogy(mess);
return;
} else if (zot(container.stage)) {
zogy("zim display - Keyboard(): The container must have a stage property");
return;
}
if (shadowColor != -1 && shadowBlur > 0) that.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
var currentStage = zdf?zdf.stage:null;
// ~~~~~~~~~~~~~~~~~ SETUP
that.labels = labels;
var maxWidth;
// Dan Zen Cat 03 - to handle any number of keys in row (always at least 10)
var maxNum = 10;
zim.loop(data[0], function (d) {
if (d.length> maxNum) maxNum = d.length;
});
var numH = maxNum;
var botArray = ["@","",".","/","away"];
if (!zot(special)) botArray.splice(1,0,special);
var textKeys = zim.copy(data[0]);
// textKeys[2].unshift("shift");
// textKeys[2].push("backspace");
textKeys[3] = textKeys[3].concat(botArray);
var numberKeys1 = zim.copy(data[1]);
// numberKeys1[2].push("backspace");
numberKeys1[3] = numberKeys1[3].concat(botArray);
var numberKeys2 = zim.copy(data[2]);
// numberKeys2[2].push("backspace");
numberKeys2[3] = numberKeys2[3].concat(botArray);
// var textKeys = [
// ["q","w","e","r","t","y","u","i","o","p"],
// ["a","s","d","f","g","h","j","k","l"],
// ["shift","z","x","c","v","b","n","m","backspace"],
// ["?123","@","",".","/","away"]
// ]
// var numberKeys1 = [
// ["1","2","3","4","5","6","7","8","9","0"],
// ["!","@","#","$","/","^","&","*","(",")"],
// ["1/2","-","'", "\"",":",";",",","?","backspace"],
// ["ABC","@","",".","/","away"]
// ];
// var numberKeys2 = [
// ["+","x","%","=","<",">","{","}","[","]"],
// ["€","£","¥", "$", "₩", "~", "`","¤","♡","☆"],
// ["2/2","_","\\","|","《","》","¡","¿","backspace"],
// ["ABC", "@","",".","/","away"]
// ];
// var eLetters = data[3][0]; // ["ė","ē","ę","ê","é","ë","è"];//ĒĘÊÉËÈ
// var uLetters = data[3][1]; // ["ū","û","ú","ü","ù"];//ŪÛÚÜÙ
// var iLetters = data[3][2]; // ["ī","į","ì","í","ï","î"];//ĪĮÌÍÏÎ
// var oLetters = data[3][3]; // ["ō","œ","ø","õ","ô","ó","ö","ò"];// ŌŒØÕÔÓÖÒ
// var aLetters = data[3][4]; // ["ā","ã","å","â","á","ä","à","æ"];// ĀÃÅÂÁÄÀÆ
// var nLetters = data[3][5]; // ["ñ","ń"];
var textKeyButtons = [];
//maateenheid horizontaal
var size = (1000-((numH-1)*5))/numH;
//statuses toestenbord
var statuses = {
def: "default",
shift: "shift",
number1: "number1",
number2: "number2"
};
var currentStatus = statuses.def;
var currentKeyboard;
var alternativeMenu;
var textBlinker;
var bigShiftOn = false;
var shiftKey;
var currentLabel;
var insertPoint = 0;
var cursorShiftMenu;
var buttonsCursor = [];
var shiftKeyIcon;
var backspaceIcon;
var backIcon;
var hideKeyBoardIcon;
var dragButton;
var dragY;
makeIcons();
makeButtons(currentStatus);
if (draggable) makeDragButton();
// ~~~~~~~~~~~~~~~~~ INTERACTIONS
this.on("mousedown", buttonPressed);
function buttonPressed(e) {
currentStage = that.stage;
if (alternativeMenu) {
that.removeChild(alternativeMenu);
}
if (cursorShiftMenu) {
if (buttonsCursor.indexOf(e.target) < 0) {
removeCursorShiftMenu();
}
}
if (!zot(e.target.na)) {
//WIJZIGINGEN STATUS keyboard
if (draggable && e.target === dragButton) {
that.tickerMouseEvent = currentStage.on("stagemousemove", function (e) {
that.mouseYAmount = e.stageY;
});
zim.Ticker.add(startDragging);
that.on("pressup", stopDragging);
dragY = e.stageY - that.localToGlobal(0, 0).y;
} else if (!zot(special) && e.target.na === special) {
that.dispatchEvent("special");
} else if (e.target.na === "shift") { //shift
shiftKeys();
} else if (e.target.toggle === "?123") { //nummers
that.removeChild(currentKeyboard);
makeButtons(statuses.number1);
} else if (e.target.toggle === "ABC") { //teksten
that.removeChild(currentKeyboard);
currentStatus = statuses.def;
makeButtons();
if (bigShiftOn) shiftKeys(true);
} else if (e.target.toggle === "1/2") {
that.removeChild(currentKeyboard);
makeButtons(statuses.number2);
} else if (e.target.toggle === "2/2") {
that.removeChild(currentKeyboard);
makeButtons(statuses.number1);
} else if (e.target.na === "away") {
hideKeyboard();
that.dispatchEvent("close");
} else if (data[3] && data[3][e.target.na]) {
makeAlternativeLetters(e.target.na);
// e.target.na === "e" ||
// e.target.na === "u" ||
// e.target.na === "i" ||
// e.target.na === "o" ||
// e.target.na === "a" ||
// e.target.na === "n") { //VARIATIES LETTERS euioan
// makeAlternativeLetters(e.target.na);
} else if (e.target.na === "return") {
addToLabel("\n");
} else if (e.target.na === "backspace") {
backspaceRemovesLetter();
} else if (e.target.na === "back") {
backspaceRemovesLetter();
} else if (e.target.na === "") {
addToLabel(" ");
} else {
addToLabel(e.target.na);
}
currentStage.update();
}
}
that.addChar = function (chara) { // do not use char - it is a keyword
if (!zot(chara) && chara.match(/^.$/)) addToLabel(chara);
};
that.removeChar = function () {
backspaceRemovesLetter(true);
};
var shiftEvent;
function shiftKeys(immediate) {
var bigShift = false;
var i;
//vanuit default
if (currentStatus === statuses.def) {
shiftKey.color = immediate ? shiftHoldBackgroundColor : shiftBackgroundColor;
//keyboard veranderen
for (i = 0; i < textKeyButtons.length - 6 - (zot(special) ? 0 : 1); i++) {
var tkb = textKeyButtons[i];
if (tkb.label.text.length > 0) {
if (tkb.na.length === 1) {
if (data[4] && data[4][tkb.label.text]) tkb.label.text = data[4][tkb.label.text];
else tkb.label.text = tkb.label.text.toUpperCase();
tkb.label.centerReg(tkb).mov(0, 6);
} else {
tkb.label.centerReg(tkb);
}
}
}
if (!immediate) {
//na halve seconde gaat groot shift aan
bigShift = true;
setTimeout(putBigShiftOn, 500);
shiftEvent = that.on("pressup", doNotPutBigShiftOn);
}
currentStatus = statuses.shift;
//vanuit shift
} else {
shiftKey.color = backgroundColor;
bigShiftOn = false;
//keyboard veranderen
for (i = 0; i < textKeyButtons.length - 6; i++) {
var tkb = textKeyButtons[i];
if (tkb.label.text.length > 0) {
if (tkb.na.length === 1) {
if (data[5] && data[5][tkb.label.text]) tkb.label.text = data[5][tkb.label.text];
else tkb.label.text = tkb.label.text.toLowerCase();
tkb.label.centerReg(tkb).mov(0, 3);
} else {
tkb.label.centerReg(tkb);
}
}
}
currentStatus = statuses.def;
}
currentKeyboard.updateCache();
if (that.stage) that.stage.update();
function putBigShiftOn() {
if (bigShift) {
bigShiftOn = true;
shiftKey.color = shiftHoldBackgroundColor;
currentKeyboard.updateCache();
if (that.stage) that.stage.update();
}
}
function doNotPutBigShiftOn(e) {
that.off("pressup", shiftEvent);
bigShift = false;
}
}
// ~~~~~~~~~~~~~~~~~ ASSETS
function makeButtons(which) {
var typeKeyboard;
var label;
var button;
var bakking;
var xPos = 0;
var yPos = 0;
var thisWidth;
var bigKey;
var thisIsSpacekey = false;
var thisKeyLetter;
var passesLetter;
var dark = false;
//zonder parameters maak ik letters
if (zot(which)) which = statuses.def;
//letters
if (which === statuses.def) {
typeKeyboard = textKeys;
//nummers1
} else if (which === statuses.number1) {
typeKeyboard = numberKeys1;
//nummers 2
} else if (which === statuses.number2) {
typeKeyboard = numberKeys2;
}
//container maken
currentKeyboard = new zim.Container(1000, 430, null, null, false).addTo(that);
//alle toetsen, door arrays heen wandelen
for (var i = 0; i < typeKeyboard.length; i++) {
if (i <= 1 || (which == statuses.def && i == 2 && typeKeyboard[2][0] != "shift")) {
xPos = (size / 2 + 2.5) * (numH - typeKeyboard[i].length);
}
for (var j = 0; j < typeKeyboard[i].length; j++) {
thisIsSpacekey = false;
thisKeyLetter = null;
dark = false;
if (typeKeyboard[i][j] == "backspace") {
bigKey = true;
thisKeyLetter = backspaceIcon;
dark = true;
} else if (typeKeyboard[i][j] == "back") {
bigKey = false;
thisKeyLetter = backspaceIcon;
dark = true;
} else if (typeKeyboard[i][j] == "shift") {
bigKey = true;
thisKeyLetter = shiftKeyIcon;
} else if ((i == 3 || (which != statuses.def && i == 2)) && j == 0) {
bigKey = true;
dark = true;
} else if (typeKeyboard[i][j] == "") {
bigKey = false;
thisIsSpacekey = true;
} else if (typeKeyboard[i][j] == "away") {
thisKeyLetter = hideKeyBoardIcon;
bigKey = true;
dark = true;
} else {
bigKey = false;
}
//brede toets: breedte instellen
if (bigKey) {
thisWidth = (size * 1.5 + 2.5);
} else if (thisIsSpacekey) {
// Dan Zen Cat 03 patch - make spacebar take up available space
thisWidth = (size + 5) * ((zot(special) ? 4 : 3) + numH-10+1-data[0][3].length) - 5;
if (data[0][3].indexOf("backspace") != -1) {
thisWidth -= size/2;
}
} else {
thisWidth = size;
}
button = new zim.Rectangle(thisWidth, size, backgroundColor, borderColor, borderWidth, corner, null, null, false).cur().addTo(currentKeyboard);
if (dark) button.addChild(new zim.Rectangle(thisWidth, size, "black", null, null, corner, null, null, false).alp(shadeAlpha));
if (thisKeyLetter) {
button.label = label = new zim.Label({ text: "", backgroundColor: "ignore", font: DS.font != null ? DS.font : null, style: false });
} else {
button.label = label = new zim.Label({
lineWidth: 10,
lineHeight: 25,
font: DS.font != null ? DS.font : null,
text: typeKeyboard[i][j],
color: color,
align: "center",
style: false
});
}
//plaatje op bakking
if (thisKeyLetter) {
var clone = thisKeyLetter.clone();
clone.scaleTo(button, 70, 70);
clone.centerReg(button);
}
if (!passesLetter) {
label.centerReg(button).mov(0, (!isNaN(label.text)) ? 7 : 3);
button.x = xPos;
button.y = yPos;
button.na = typeKeyboard[i][j];
if (i == 2 && j == 0 && which == statuses.number1) button.toggle = "1/2";
if (i == 2 && j == 0 && which == statuses.number2) button.toggle = "2/2";
if (i == 3 && j == 0 && which == statuses.def) button.toggle = "?123";
if (i == 3 && j == 0 && which != statuses.def) button.toggle = "ABC";
if (button.toggle) label.mov(0, 3);
textKeyButtons.push(button);
if (button.na == "shift") {
shiftKey = button;
}
xPos = button.x + button.width + 5;
} else {
passesLetter = false;
xPos += 67.33;
}
}
yPos += size + 5;
xPos = 0;
}
currentKeyboard.cache(borderWidth ? -borderWidth : 0, borderWidth ? -borderWidth : 0, borderWidth ? currentKeyboard.width + borderWidth * 2 : currentKeyboard.width, borderWidth ? currentKeyboard.height + borderWidth * 2 : currentKeyboard.height);
}
function makeAlternativeLetters(letter) {
var thisArray = data[3][letter];
var mouseReleased = false;
var alternativeMenuIsmade = false;
var timeWait;
// switch (letter) {
// case "e":
// thisArray = eLetters;
// break;
// case "u":
// thisArray = uLetters;
// break;
// case "i":
// thisArray = iLetters;
// break;
// case "o":
// thisArray = oLetters;
// break;
// case "a":
// thisArray = aLetters;
// break;
// case "n":
// thisArray = nLetters;
// break;
// default:
// break;
// }
timeWait = zim.timeout(500, makeAlternatemenu, null, "ms");
var mouseUpEvent = that.on("pressup", mouseUp);
function mouseUp(e) {
mouseReleased = true;
that.off("pressup", mouseUpEvent);
if (!alternativeMenuIsmade) {
addToLabel(letter);
}
}
function makeAlternatemenu() {
var label,
bakking,
button,
overlay,
xPos = 0,
thisLetter;
timeWait.clear();
if (!mouseReleased) {
alternativeMenuIsmade = true;
alternativeMenu = new zim.Container(1000, size, null, null, false).addTo(that, 0);
alternativeMenu.y = - size - 5;
for (var i = 0; i < thisArray.length; i++) {
if (currentStatus === statuses.shift) {
thisLetter = thisArray[i].toUpperCase();
} else {
thisLetter = thisArray[i];
}
label = new zim.Label({
lineWidth: 10,
lineHeight: 25,
text: thisLetter,
font: DS.font != null ? DS.font : null,
color: color,
align: "center",
style: false
});
button = new zim.Rectangle(size, size, backgroundColor, borderColor, borderWidth, corner, null, null, false).addTo(alternativeMenu);
overlay = new zim.Rectangle(size, size, "white", null, null, corner, null, null, false).alp(.2);
button.addChild(overlay);
label.center(button);
button.na = thisArray[i];
button.x = xPos;
xPos += size + 5;
}
if (that.stage) that.stage.update();
}
}
}
function makeIcons() {
//shift
shiftKeyIcon = new zim.Shape({ style: false });
shiftKeyIcon.graphics.f(color).p("AhIFoIAAjYIixAAID5n3ID6H3IixAAIAADYgAjHBxICeAAIAADYIBTAAIAAjYICeAAIjImSg");
shiftKeyIcon.setBounds(-51 / 2, -72 / 2, 51, 72);
//backspace
backspaceIcon = new zim.Container({ style: false });
var backspaceShape1 = new zim.Shape({ style: false });
backspaceShape1.graphics.f(color).p("ACgC+IigigIifCgQgGAGgJAAQgJAAgGgGQgGgGgBgJQABgJAGgGICgigIigifQgGgGgBgJQABgJAGgGQAGgGAJAAQAIAAAHAGICfCgICgigQAGgGAJAAQAJAAAGAGQAGAGABAJQgBAJgGAGIigCfICgCgQAGAGABAJQgBAJgGAGQgGAGgJAAQgJAAgGgGg");
backspaceShape1.setTransform(82.6, 32);
backspaceShape1.addTo(backspaceIcon);
var backspaceShape2 = new zim.Shape({ style: false });
backspaceShape2.graphics.f(color).s().p("AkhFAQgcAAgUgUIkHj6QgVgUAAgeQAAgdAVgVIEHj6QAUgTAcAAINKAAQAdAAAUAUQAUAUAAAdIAAH1QAAAdgUATQgUAVgdAAgAk0kOIkGD8QgIAHAAALQAAALAIAIIEGD7QAIAHALAAINKAAQALAAAIgIQAHgHAAgLIAAn1QAAgLgHgIQgIgIgLAAItKAAQgLAAgIAHg");
backspaceShape2.setTransform(62.2, 32);
backspaceShape2.addTo(backspaceIcon);
backspaceIcon.setBounds(0, 0, 125, 64);
//keyboardAway
hideKeyBoardIcon = new zim.Container({ style: false });
hideKeyBoardIcon.setBounds(0, 0, 147, 86);
var hideKeyBoardIconArray = [
{ p: ("Ai+heIF9AAIi/C9g"), transform: [73.4, 76] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [128.4, 43.2] },
{ p: ("AnNAzIAAhlIObAAIAABlg"), transform: [73, 43.2] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [18.8, 43.2] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [128.2, 29.5] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [114.5, 29.5] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [100.8, 29.5] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [87.1, 29.5] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [73.4, 29.5] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [59.7, 29.5] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [46, 29.5] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [32.3, 29.5] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [18.6, 29.5] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [128, 15.8] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [114.3, 15.8] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [100.6, 15.8] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [86.9, 15.8] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [73.2, 15.8] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [59.5, 15.8] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [45.8, 15.8] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [32.1, 15.8] },
{ p: ("AgyAzIAAhlIBlAAIAABlg"), transform: [18.4, 15.8] },
{ p: ("AphEnQgzAAgkgkQglglAAgzIAAlVQAAgzAlglQAkgkAzAAITDAAQAzAAAkAkQAlAlAAAzIAAFVQAAAzglAlQgkAkgzAAgAqjjtQgcAcAAAnIAAFVQAAAnAcAbQAbAcAnAAITDAAQAnAAAcgcQAbgbAAgnIAAlVQAAgngbgcQgcgcgnAAIzDAAQgnAAgbAcg"), transform: [73.4, 29.5] }
];
var thisShape;
for (var i = 0; i < hideKeyBoardIconArray.length; i++) {
thisShape = new zim.Shape({ style: false });
thisShape.graphics.f(color).s().p(hideKeyBoardIconArray[i].p);
thisShape.setTransform(hideKeyBoardIconArray[i].transform[0], hideKeyBoardIconArray[i].transform[1]);
thisShape.addTo(hideKeyBoardIcon);
}
}
function makeDragButton() {
dragButton = new zim.Rectangle((size * 1.5 + 2.5) + 2.5, size, backgroundColor, borderColor, borderWidth, corner, null, null, false).addTo(that, 0).cur();
var rect;
for (var i = 0; i < 4; i++) {
rect = new zim.Rectangle(dragButton.width * 0.4, 4, color, null, null, null, null, null, false).centerReg(dragButton).alp(.2);
rect.y -= -22 + (i * 15);
}
dragButton.x = (8.5 * size) + (40);
dragButton.y = - size - 5;
dragButton.na = "drag";
}
function hideKeyboard() {
that.hide();
}
function startDragging() {
if (that.mouseYAmount) that.y = that.parent.globalToLocal(0, that.mouseYAmount - dragY).y;
}
function stopDragging() {
currentStage.off("pressmousemove", that.tickerMouseEvent);
zim.Ticker.remove(startDragging);
}
that.setBounds(1000,400-(numH-10)*26); // Dan Zen for any size keyboard
// ~~~~~~~~~~~~~~~~~ LABELS AND CURSOR
function positionBlinker() {
if (!currentLabel || !textBlinker) return;
// Dan Zen added 9.5.0 using CreateJS Label to avoid padding and backing issues and addition of bounds x for align issues
var positionXBlinker = currentLabel.label.x + currentLabel.label.getBounds().x;
for (var i=0; i", "x"] : ["<", ">"];
var label;
var bakking;
var button;
var point;
buttonsCursor = [];
point = currentLabel.localToLocal(0, 0, that);
cursorShiftMenu = new zim.Container({ style: false }).addTo(that).pos({ x: point.x, y: point.y + currentLabel.height + 15, reg: true }).cur();
for (var i = 0; i < tekens.length; i++) {
bakking = new zim.Rectangle(size, size, placeBackgroundColor, borderColor, borderWidth, corner, null, null, false);
if (tekens[i] == "x") new zim.Rectangle(size, size, "black", null, null, corner, null, null, false).alp(shadeAlpha).addTo(bakking);
button = new zim.Label({
lineWidth: 10,
// lineHeight:58, // ?
text: tekens[i],
backing: bakking,
font: DS.font != null ? DS.font : null,
color: placeColor,
align: "center",
valign: "center",
style: false
});
button.pos(0, 0, zim.LEFT, zim.TOP, cursorShiftMenu).cache();
button.x = button.x + i * (size + 5);
buttonsCursor.push(button);
}
point = currentLabel.localToLocal(0, 0, that);
cursorShiftMenu.x = point.x;
cursorShiftMenu.y = point.y + currentLabel.height + 15;
cursorShiftMenu.on("click", verschuifCursor);
function verschuifCursor(e) {
if (buttonsCursor.indexOf(e.target) == 0) {
if (insertPoint > 0) insertPoint--;
} else if (buttonsCursor.indexOf(e.target) == 1) {
if (insertPoint < currentLabel.text.length) insertPoint++;
} else {
removeCursorShiftMenu();
}
positionBlinker();
}
if (that.stage) that.stage.update();
}
function removeCursorShiftMenu() {
if (!cursorShiftMenu) return that;
cursorShiftMenu.removeAllEventListeners();
that.removeChild(cursorShiftMenu);
cursorShiftMenu = null;
}
function addToLabel(letter) {
if (!currentLabel) return;
var measureField;
var widthMeasureField;
// backspace
if (letter === "del") {
if (currentLabel) currentLabel.text = [currentLabel.text.slice(0,insertPoint-1),currentLabel.text.slice(insertPoint)].join('');
insertPoint--;
makeWidthsArray();
} else {
if (currentStatus === statuses.shift) {
letter = letter.toUpperCase();
}
var textBeforeCheck = currentLabel.text;
measureField = currentLabel.clone().removeFrom();
measureField.text = letter;
widthMeasureField = measureField.label.getMeasuredWidth();
if (!currentLabel.widthArray) {
currentLabel.widthArray = [currentLabel.breedte];
} else {
currentLabel.widthArray.splice(insertPoint,0,widthMeasureField);
}
//toevoegen in string
if (insertPoint=0; i--) {
// sumUp += currentLabel.widthArray[i];
// if (point.x < sumUp-currentLabel.widthArray[i]/2) {
// insertPoint = i;
// found = true;
// break;
// }
// }
// var rightOfLabel = currentLabel.getBounds().width + currentLabel.getBounds().x;
// zog(rightOfLabel);
// zog(currentLabel.widthArray)
// for (var i=0; i 0) {
makeCursorShiftmenu();
}
if (cursorShiftMenu && currentLabel) {
if (currentLabel.text.length > 0) {
point = currentLabel.localToLocal(0, 0, that);
cursorShiftMenu.x = point.x;
cursorShiftMenu.y = point.y+currentLabel.height+15;
} else {
removeCursorShiftMenu();
}
}
}
function makeWidthsArray() {
if (!currentLabel) return;
var measureField = new Label("");
currentLabel.widthArray = [];
for (var i=0; i 0) {
if (that.selectedIndex > 0) addToLabel("del");
if (once) stopRemoval();
else that.on("pressup", stopRemoval);
} else {
addToLabel("del");
}
}
function stopRemoval() {
removalOkay = false;
if (timeOut) timeOut.clear();
that.off("pressup", stopRemoval);
}
removeLetter();
timeOut = zim.timeout(300, haalWeg, null, "ms");
if (that.stage) that.stage.update();
}
function setLabels() {
for (var i = 0; i < labels.length; i++) {
labels[i].clickEvent = labels[i].on("click", activateLabel);
}
}
setLabels();
function unsetLabels() {
if (labels.length > 1) {
for (var i = 0; i < labels.length; i++) {
labels[i].off("click", labels[i].clickEvent);
}
}
}
function makeCursor() {
if (textBlinker) return;
currentLabel = labels[0];
maxWidth = (currentLabel && currentLabel.label.lineWidth) ? currentLabel.label.lineWidth : 10000;
if (currentLabel) {
textBlinker = new zim.Rectangle(3, currentLabel.height - ((currentLabel.paddingVertical && currentLabel.background) ? currentLabel.paddingVertical * 2 : 0), cursorColor, null, null, null, null, null, false).center(currentLabel);
textBlinker.x = 0;
textBlinker.visible = false;
textBlinker.animate({
obj: { alpha: 0 },
rewind: true,
loop: true,
loopWait: 750,
time: 250,
id: "knipperTekst",
timeUnit: "ms"
});
for (var j = 0; j < labels.length; j++) {
labels[j].widthArray = [0];
}
makeWidthsArray();
}
}
makeCursor();
function removeCursor() {
zim.stopAnimate("knipperTekst");
if (currentLabel) currentLabel.removeChild(textBlinker);
textBlinker = null;
currentLabel = null;
}
// ~~~~~~~~~~~~~~~ GETTER SETTER PROPS
Object.defineProperty(this, 'selectedLabel', {
get: function() {
return currentLabel;
},
set: function(label) {
var obj = {target:label};
activateLabel(obj);
that.hidePlace();
}
});
Object.defineProperty(this, 'selectedIndex', {
get: function() {
return insertPoint;
},
set: function(index) {
insertPoint = index;
positionBlinker();
}
});
// ~~~~~~~~~~~~~~~ METHODS
this.show = function(index) {
that.addTo(container);
// that.resize();
if (!zot(index)) {
var obj = {target:labels[index]};
activateLabel(obj);
}
if (textBlinker) textBlinker.visible = true;
that.toggled = true;
return that;
};
this.hide = function() {
that.removeFrom(container);
if (textBlinker) textBlinker.visible = false;
currentStage.update();
that.toggled = false;
return that;
};
this.toggle = function(state) {
if (state===true) that.show();
else if (state===false) that.hide();
else if (that.parent) that.hide();
else that.show();
return that;
};
this.showPlace = function() {
makeCursorShiftmenu();
return that;
};
this.hidePlace = function() {
removeCursorShiftMenu();
return that;
};
this.addLabels = function(labs) {
if (!Array.isArray(labs)) labs = [labs];
for (var i=labs.length-1; i>=0; i--) {
var ind = labels.indexOf(labs[i]);
if (ind >= 0 || labs[i].type != "Label") labs.splice(i, 1);
else labs[i].widthArray = [0];
}
unsetLabels();
labels = labels.concat(labs);
setLabels();
makeCursor();
if (textBlinker) textBlinker.visible = true;
return that;
};
this.removeLabels = function(labs) {
if (!Array.isArray(labs)) labs = [labs];
unsetLabels();
for (var i=0; i= 0) labels.splice(ind, 1);
}
setLabels();
if (labels.length == 0) {
if (currentLabel) removeCursor();
} else {
if (currentLabel && labels.indexOf(currentLabel) == -1) {
removeCursor();
makeCursor();
}
}
return that;
};
var background = new zim.Rectangle(this.width, this.height, zim.clear, null, null, null, null, null, false).addTo(this).expand().bot();
background.on("mousedown", function(){});
background.on("click", function(){});
this.resize = function() {
that.scaleTo(currentStage, 100-margin*2/currentStage.width*100, 50-margin*2/currentStage.height*100);
that.y = currentStage.height - that.height - margin;
that.x = currentStage.width/2 - that.width/2;
if (currentLabel && cursorShiftMenu) {
var point = currentLabel.localToLocal(0, 0, that);
cursorShiftMenu.x = point.x;
cursorShiftMenu.y = point.y + currentLabel.height + 15;
}
if (that.stage) that.stage.update();
return that;
};
this.resize();
if (that.selectedLabel) that.selectedIndex = that.selectedLabel.text.length;
// Dan Zen added ZIM 10.5.1
if (hardKeyboard) {
this.keydownEvent = function(e) {
if (!that.stage) return;
var k = that;
if (zot(k)) return;
if (e.keyCode==35) k.selectedIndex = k.selectedLabel.text.length; // end
if (e.keyCode==36) k.selectedIndex = 0; // home
if (e.keyCode==37) k.selectedIndex = k.selectedIndex-1; // left
if (e.keyCode==39) k.selectedIndex = k.selectedIndex+1; // right
if (e.keyCode==46) { // del
if (k.selectedIndex < k.selectedLabel.text.length) {
k.selectedIndex = k.selectedIndex + 1;
k.removeChar();
}
}
if (e.keyCode==8) {
e.preventDefault();
k.removeChar(); // backspace
}
k.addChar(e.key);
if (that.stage) that.stage.update();
};
window.addEventListener("keydown", this.keydownEvent);
}
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
var kb = new zim.Keyboard(labels, backgroundColor, color, shiftBackgroundColor, shiftHoldBackgroundColor, placeBackgroundColor, cursorColor, shadeAlpha, margin, corner, draggable, placeClose, shadowColor, shadowBlur, container, data, place, special, rtl, hardKeyboard, layout, style, this.group, inherit);
return that.cloneProps(kb);
};
this.dispose = function(a,b,disposing) {
background.removeAllEventListeners();
background = null;
if (that.keydownEvent) window.removeEventListener("keydown", that.keydownEvent);
for(var i=0; i0)) val = 5;
var badIndex = zot(that.list.selectedIndex) || that.list.selectedIndex<0;
if (badIndex) that.currentValue = null;
that.lastIndex = that.list.selectedIndex;
switch(val) {
case 0: // add
if (autoAdd) {
var index = Math.max(0,that.list.selectedIndex);
that.add(index);
}
that.orgType = "add";
break;
case 1: // up
if (badIndex) break;
if (autoPosition) {
var index = that.list.selectedIndex;
that.up(index);
}
that.orgType = "up";
break;
case 2: // down
if (badIndex) break;
if (autoPosition) {
var index = that.list.selectedIndex;
that.down(index);
}
that.orgType = "down";
break;
case 3: // top
if (badIndex) break;
if (autoPosition) {
var index = that.list.selectedIndex;
that.toTop(index);
}
that.orgType = "top";
break;
case 4: // bottom
if (badIndex) break;
if (autoPosition) {
var index = that.list.selectedIndex;
that.toBottom(index);
}
that.orgType = "bottom";
break;
case 5: // remove
if (badIndex) break;
if (autoRemove) {
var index = that.list.selectedIndex;
that.remove(index);
}
that.orgType = "remove";
break;
}
});
this.add = function(index, item, clone) {
if (zot(index)) index = that.lastIndex;
if (zot(item)) item = "";
if (addForward) {
var index = Math.min(that.list.length, Math.max(0,that.list.selectedIndex)+1);
} else {
var index = Math.max(0,that.list.selectedIndex);
}
that.list.addAt(item, index, clone);
that.list.selectedIndexPlusPosition = index;
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
return that;
};
this.up = function(index) {
if (zot(index)) index = that.lastIndex;
var button = that.list.items[index];
if (zot(button)) return that;
that.list.removeAt(1, index);
that.list.addAt(button, index-1);
that.list.selectedIndexPlusPosition = Math.max(0,index-1);
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
return that;
};
this.down = function(index) {
if (zot(index)) index = that.lastIndex;
var button = that.list.items[index];
if (zot(button)) return that;
that.list.removeAt(1, index);
that.list.addAt(button, index+1);
that.list.selectedIndexPlusPosition = Math.min(that.list.length-1,index+1);
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
return that;
};
this.toTop = function(index) {
if (zot(index)) index = that.lastIndex;
var button = that.list.items[index];
if (zot(button)) return that;
that.list.removeAt(1, index);
that.list.addAt(button, 0);
that.list.first();
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
return that;
};
this.toBottom = function(index) {
if (zot(index)) index = that.lastIndex;
var button = that.list.items[index];
if (zot(button)) return;
that.list.removeAt(1, index);
that.list.addAt(button, that.list.length);
that.list.last();
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
return that;
};
this.remove = function(index) {
if (zot(index)) {
if (that.list.selectedIndex >= 0) index = that.list.selectedIndex;
else return that;
}
var same = index == that.list.selectedIndex;
that.removedItem = that.list.items[index];
that.list.removeAt(1, index);
if (same) {
if (!removeForward) {
index = Math.max(0,index-1);
}
} else {
index = that.list.selectedIndex;
}
that.list.selectedIndexPlusPosition = Math.min(that.list.length-1, index);
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
return that;
};
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Organizer(width, list, useAdd, useRemove, usePosition, autoAdd, autoRemove, autoPosition, addForward, removeForward, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, spacing, corner, keyEnabled, gradient, gloss, backdropColor, style, that.group, inherit));
};
this.dispose = function(a,b,disposing) {
buttons = null;
if (!disposing) {
that.zimTabs_dispose(true); // will go to Container dispose
}
return true;
};
};
zim.extend(zim.Organizer, zim.Tabs, ["clone", "dispose"], "zimTabs", false);
//-67.3
//
/*--
zim.Scrambler = function(tile, keys, keyProperty, scramble, time, wait, num, shadowColor, shadowBlur, swap, swapLock, style, group, inherit)
Scrambler
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Takes a ZIM Tile and scrambles its items allowing the items to be dragged to unscramble.
Works on horizontal, vertical or grid versions of Tile (as in one column, one row or multiples)
Dispatches a "complete" event when done.
Can pass in an optional keys array that must match key properties
or an existing property of type keyType.
This allows, for instance, matching duplicate letters or colors.
See: https://zimjs.com/cat/scrambler.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// tile a rectangle with a color series, a dark border of width 3
// 4 columns and 1 row with a spacingH of 10
var tile = new Tile(new Rectangle(100,100,series(orange, green, blue, pink)), 4, 1, 10);
// add the tile to the Scrambler - by default it scrambles
var scrambler = new Scrambler(tile).center();
// when the tile is unscrambled it calls the complete function
scrambler.on("complete", function () {
zogg("Yay!");
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
tile - an ZIM Tile
keys (default null) - An optional array of values that the order of the tile must match
Without keys, Scrambler will match the exact starting order
but sometimes there are multiple answers like two letter Ts or three color blues
To solve this issue, a keys array can be provided
Each tile should be given a key property to match the desired keys array
For instance if keys = ["big", "small", "big", "small", "medium"]
then each tile item should be given a item.key = "big", etc.
The "complete" event will be dispatched when the tile key properties are in the order of the keys
Also see keyProperty below for an alternative.
keyProperty (default null) - An optional tile item property to use to match the keys array (must have a keys array)
For example, if keys = ["L", "O", "V", "E", "L", "Y"]
There are two "L" items so matching the starting order is not necessary
as the L items could be swapped and still be a correct answer
If the items are ZIM Label objects (use the Label backing property to make tiles)
then set the keyProperty to "text" and this will be used to match the keys array
Another example - if keys = [blue, green, blue, red]
then set keysArray to "color" if a set of Rectangles are tiled with these colors
scramble (default true) - set to false to not scramble the tile - see also the scramble() method
time (default null) - if scramble is set, this is the time in seconds to animate the scramble - see also ZIM TIME constant
wait (default null) - if scramble is set, this is the time in seconds to wait to scramble - see also ZIM TIME constant
num (default 1) - the number of times it will scramble within the time given if a time is given otherwise always just one
this is good to scramble a small number of things - for instance set to 3 to visibly scramble 4 things...
shadowColor - (default rgba(0,0,0,.3)) set to -1 for no shadow
shadowBlur - (default 5) how blurred the shadow is if the shadow is set
swap - (default false) set to true to not automatically shift tiles and swap the dragged tile with the tile that is dropped on
swapLock - (default false) set to true to lock tiles that are in the right spot - will set swap to true
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
scramble(time, wait, num) - scramble the tile - this is done by default when making the Scrambler
but the default can be set to false and scramble called manually - or to rescramble, etc.
time and wait default to 0 and are the seconds to animate and wait to animate - also see ZIM TIME constant
num is how many times to scramble within the time - set to 3 for instance to scramble a small number of items
note that the tiles cannot be dragged from when called to when done scrambling
solve(time, wait, disable) - solve the tile - so arrange the tile in the start order
time and wait default to 0 and are the seconds to animate and wait to animate - also see ZIM TIME constant
disable defaults to true and will stop the tile items from being draggable after solved
this uses a noMouse() so mouse() can be called on each tile item at a later point if desired
test() - returns true if tiles match starting orientation or keys if keys provided
testItem(item, index) - test a specific item in the Scrambler to see if correct - index is optional otherwise it will calculate it
note - there is a "complete" event and complete property so usually there is no need to test an item
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
complete - get whether the Scrambler is complete - also see the "complete" event
starts - an array of start indexes (will be [0,1,2,3...])
order - an array of the current index order (will be the scrambled order - eg. [3,2,0,1...])
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "complete" event when the tile changes to the same order as the start order
dispatches a "scrambled" event when the tile is finished scrambling
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+67.35
zim.Scrambler = function(tile, keys, keyProperty, scramble, time, wait, num, shadowColor, shadowBlur, swap, swapLock, style, group, inherit) {
var sig = "tile, keys, keyProperty, scramble, time, wait, num, shadowColor, shadowBlur, swap, swapLock, style, group, inherit";
var duo; if (duo = zob(zim.Scrambler, arguments, sig, this)) return duo;
z_d("67.35");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Scrambler";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(tile)) tile = DS.tile!=null?DS.tile:tile;
if (zot(keys)) keys = DS.keys!=null?DS.keys:null;
if (zot(keyProperty)) keyProperty = DS.keyProperty!=null?DS.keyProperty:null;
if (zot(scramble)) scramble = DS.scramble!=null?DS.scramble:true;
if (zot(time)) time = DS.time!=null?DS.time:0;
if (zot(wait)) wait = DS.wait!=null?DS.wait:0;
if (zot(num)) num = DS.num!=null?DS.num:1;
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:5;
if (zot(swap)) swap=DS.swap!=null?DS.swap:false;
if (zot(swapLock)) swapLock=DS.swapLock!=null?DS.swapLock:false;
if (swapLock) swap = true;
if (zot(tile)) return;
tile.addTo(this);
var that = this;
that.complete = true;
var timeType = getTIME(time);
getTIME(wait);
var tileWidth = (tile.width+tile.spacingH)/tile.cols;
var tileHeight = (tile.height+tile.spacingV)/tile.rows;
var startX, startY;
tile.on("mousedown", function (e) {
if (swapLock) {
var current = tile.current;
if (that.testItem(e.target, current.indexOf(e.target))) {
e.target.noMouse();
e.target.noDrag();
return;
}
}
startX = e.target.x;
startY = e.target.y;
if (shadowColor != -1 && shadowBlur > 0) {
var shad = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
if (e.target.backing) e.target.backing.shadow = shad;
else e.target.shadow = shad;
}
if (that.upEvent) tile.off("pressup", that.upEvent);
that.upEvent = tile.on("pressup",function (e) {
var good = true;
if (swapLock) {
var cbg = e.target.boundsToGlobal();
var index = tile.hitTestGrid(tile.width, tile.height, tile.cols, tile.rows, cbg.x+cbg.width/2, cbg.y+cbg.height/2, null, null, tile.spacingH, tile.spacingV, null, "open");
if (zot(index)) good = false;
else {
var currentTile = current[index[0]];
if (e.target == currentTile) good = false;
else good = !that.testItem(currentTile, index[0]);
}
}
if (swap && good) doMove(e);
e.target.mouseEnabled = false;
e.target.animate({
props:{x:startX, y:startY},
time:.1,
id:"zimScrambler",
timeUnit:"seconds",
call:function () {
if (!that.complete && that.test()) {
that.complete = true;
that.dispatchEvent("complete");
}
if (shadowColor != -1 && shadowBlur > 0) {
if (e.target.backing) e.target.backing.shadow = null;
else e.target.shadow = null;
}
e.target.mouseEnabled = true;
}
});
}, null, true); // once
if (!swap) {
if (that.moveEvent) tile.off("pressmove", that.moveEvent);
that.moveEvent = tile.on("pressmove", function (e) {
// get current and current row and col
doMove(e);
});
}
});
function doMove(e) {
var current = e.target;
current.stopAnimate();
var cbg = current.boundsToGlobal();
var cdata = tile.hitTestGrid(tile.width, tile.height, tile.cols, tile.rows, cbg.x+cbg.width/2, cbg.y+cbg.height/2, null, null, tile.spacingH, tile.spacingV, null, "open");
if (zot(cdata)) return;
zim.loop(tile, function (t) {
// t.paused===false means it is animating
// is a bug in animate where if animate is interupted it may be left in a paused false state
// stopAnimate will reset it
if (t==current || t.paused===false) return; // continue loop
var tbg = t.boundsToGlobal();
var tdata = tile.hitTestGrid(tile.width, tile.height, tile.cols, tile.rows, tbg.x+tbg.width/2, tbg.y+tbg.height/2, null, null, tile.spacingH, tile.spacingV, null, "open");
if (zot(tdata)) return;
// current row == tile row
if (cdata[2]==tdata[2] && ((t.x>=current.x && t.x<=current.x+tileWidth/2) || (t.x<=current.x && t.x>=current.x-tileWidth/2))) {
var temp = t.x;
t.mouseEnabled = false;
t.top().ord(-1);
t.animate({
props:{x:startX},
time:.2,
id:"zimScrambler",
timeUnit:"seconds",
call:function () {
t.mouseEnabled = true;
if (swap && !that.complete && that.test()) {
that.complete = true;
that.dispatchEvent("complete");
}
}
});
startX = temp;
}
// current column == tile column
if (cdata[1]==tdata[1] && ((t.y>=current.y && t.y<=current.y+tileHeight/2) || (t.y<=current.y && t.y>=current.y-tileHeight/2))) {
var temp = t.y;
t.mouseEnabled = false;
t.top().ord(-1);
t.animate({
props:{y:startY},
time:.201,
override:false,
id:"zimScrambler",
timeUnit:"seconds",
call:function () {
t.mouseEnabled = true;
if (swap && !that.complete && that.test()) {
that.complete = true;
that.dispatchEvent("complete");
}
}
});
startY = temp;
}
}, true);
}
this.test = function () {
var current = tile.current;
return zim.loop(current, function (item, i) {
if (zot(item)) return false;
if (!that.testItem(item, i)) return false;
});
};
this.testItem = function(item, i) {
if (zot(item)) return;
if (zot(i)) i = tile.current.indexOf(item);
if (keys) {
var key = zot(keyProperty)?item.key:item[keyProperty];
if (key != keys[i]) return false;
} else {
if (tile.items[i] != item) return false;
}
return true;
};
this.starts = [];
this.order = [];
zim.loop(tile.rows*tile.cols, function (i) {
that.order.push(i);
});
var startOrder = that.order.slice();
tile.loop(function (t) {
that.starts.push({x:t.x, y:t.y});
});
this.inactive = false;
this.scramble = function(time, wait, num) {
if (zot(wait)) wait = 0;
if (zot(time)) time = 0;
if (zot(num) || time==0) num = 1;
offScrambler();
zim.timeout(wait, function () {
if (time>0) zim.interval(time/num, doScramble, num, true);
else doScramble();
});
setTimeout(function () {
that.complete = false;
tile.loop(function (t) {
t.mouse();
});
that.mouse();
tile.drag({boundary:tile});
}, timeType=="s"?(wait+time)*1000:wait+time);
function doScramble() {
var answer = true;
var times = 0;
// if rand order does not produce an answer then we are good!
while (answer && times<50) {
times++;
zim.shuffle(that.order);
answer = zim.loop(that.order, function (o, i) {
var item = tile.getChildAt(o);
if (keys) {
var key = zot(keyProperty)?item.key:item[keyProperty];
if (key != keys[i]) return false;
} else {
if (tile.items[i] != item) return false;
}
});
}
// scramble location (not tile.remake()) to order
moveTiles(that.order, time/num);
zim.timeout(time, function () {
that.dispatchEvent("scrambled");
})
}
};
if (scramble) {
that.scramble(time, wait, num);
} else {
that.added(function () {
tile.drag({boundary:tile});
});
}
function offScrambler() {
if (that.upEvent) tile.off("pressup", that.upEvent);
if (that.moveEvent) tile.off("pressmove", that.moveEvent);
tile.noDrag();
if (wait+time>0) {
that.noMouse();
}
}
function moveTiles(order, time, wait, disable) {
zim.stopAnimate("zimScrambler");
// not children but items - which never change from start
zim.loop(tile.items, function (item, i, t) {
var start = that.starts[order[i]];
if (time) {
item.animate({
props:{x:start.x, y:start.y},
time:time,
ease:wait?"quadInOut":"quadOut",
wait:wait,
timeUnit:"seconds",
id:"zimScrambler"
});
} else {
item.loc(start);
if (that.stage) {
item.drag({boundary:tile});
} else {
if (i==t-1) {
that.added(function () {
tile.drag({boundary:tile});
});
}
}
}
});
}
this.solve = function(time, wait, disable) {
if (zot(disable)) disable = true;
if (zot(wait)) wait = 0;
if (zot(time)) time = 0;
if (wait+time==0 && disable) that.noMouse();
setTimeout(function () {
that.order = startOrder.slice();
offScrambler();
moveTiles(that.order, time, 0, disable);
}, timeType=="s"?wait*1000:wait);
if (!disable) {
setTimeout(function () {
that.mouse();
tile.drag({boundary:tile});
}, timeType=="s"?(wait+time)*1000:wait+time);
}
};
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
this.dispose = function(a,b,disposing) {
tile.removeAllEventListeners();
if (!disposing) {
that.zimContainer_dispose(true);
if (that.stage) that.stage.update();
}
return true;
};
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Scrambler(tile.clone(), keys, keyProperty, scramble, time, wait, num, shadowColor, shadowBlur, swap, swapLock, style, that.group, inherit));
};
};
zim.extend(zim.Scrambler, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-67.35
/*--
zim.Connectors = function(width, height, points, node, line, linear, linearWrap, linearOrder, num, snapH, snapV, dropType, deleteNode, dblclick, fullMove, min, max, boundary, expand, nodeRollColor, nodeRollBorderColor, nodeSelectedColor, nodeSelectedBorderColor, baseColor, baseBorderColor, baseRollover, rootLock, grandChildren, dblclickTime, style, group, inherit)
Connectors
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Adds nodes (any DisplayObject - default a Circle) that can be dragged to draw a connector line.
There are three main uses for Connectors:
1. Connecting dots like in coloring books - use linear:true
2. Making hieararchy type drawings - use snaps
3. Connecting objects like boxes together - pass in objects to the points
The num parameter limits the number of lines that can be drawn from a node.
The dropType can be set to require nodes to be dropped on or off other nodes (or the default, any).
There are min and max distances the connections can be made.
These and the other parameters provide a variety of game and puzzle options.
The Line can be set to have start and end heads.
The lineType in the Line can be set to "straight", "corner" or "curve"
Line also accepts points for any arrangement of a connector
but in this version, these have not been used in Connectors.
Currently, there are no pre-made lines - the user would have to make these.
In future versions, we will look at making nodes and lines based on a ZIM Hierarchy object.
This would also allow use to handle undo, redo and save.
See: https://zimjs.com/cat/connectors.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// draws four general connectors that can be connected to one another in a box
// adjust connector nodes after connections are complete
var connectors = new Connectors({linear:true}).center();
connectors.on("complete", function () {
connectors.nodes.loop(function (node) {
node.radius = 5;
node.color = red;
});
// or hide connectors
// connectors.nodes.alp(0);
stage.update();
});
END EXAMPLE
EXAMPLE
// make a grid of connectors and only connect to other nodes
// do not let user delete a node or doubleclick to move a node
var points = [];
var spacing = 60;
loop(10, function (i) {
loop(10, function (j) {
points.push([i*spacing, j*spacing]);
});
});
var connectors = new Connectors({
points:points,
node:new Rectangle(12,12,purple).centerReg(),
line:new Line({color:purple, thickness:12}),
nodeRollColor:orange,
dropType:"on",
dblclick:false,
deleteNode:false,
max:70
}).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default null) the width of the connnectors container or will grow with added connectors
height - (default null) the height of the connnectors container or will grow with added connectors
points - (default [[0,0], [100,0], [100,100], [0,100]]) an array of point arrays for the connectors
or can specify a ZIM Blob or Squiggle to place connectors on their points
the Blob or Squiggle do not need to be added to the stage
use the recordPoints(true) method of the Blob or Squiggle or see https://zimjs.com/nio/paths.html
or can specify an array of a base (that connectors nodes will be added to) and baseInfo as follows:
[[base, baseInfo], [base, baseInfo], [base, baseInfo], etc.]
the baseInfo can be a number of nodes to place around all base sides
or baseInfo can be an array with three different formats:
[all]
[left/right, top/bottom]
[left, right, top, bottom]
These can be numbers greater than 0 for the number of nodes on the side
or 0 for no nodes on the side
or -1 for both corners on the side
or -2 for the first corner on the side
or -3 for the second corner on the side
node - (default new Circle(10, grey, grey)) the DisplayObject to use as a node - should be centerReg()
line - (default new zim.Line({thickness:3, color:tin, strokeObj:{caps:"round"})) the line to use as the connector
ZIM Line has a lineType parameter for "straight", "corner", and "curve" which will affect the connector lines
ZIM Line has a lineOrientation parameter of "auto", "horizontal" or "vertical" that will affect the connector lines
ZIM Line as curveH and curveV settings that will adjust the lines for the "curve" setting
the caps should be set to "round" if drawing with clear or transparent nodes
linear - (default false) lines will only connect to points that are next to one another (in the point order)
this is good for connecting dots
linearWrap - (default true) let the first point connect to the last point in the linear setting
linearOrder - (default false) require the points to be connected in order
num - (default null) set the maximum number of lines that can come from a node
snapH - (default null) snap the nodes to a provided horizontal distance
snapV - (default null) snap the nodes to a provided vertical distance
dropType - (default "any") determines what happens when a node is dropped as follows:
"any" lets the node be dropped anywhere (and may be snapped)
"on" will save the node if dropped on an existing node otherwise it is removed or put back to where it is dragged from
"off" will save the node if not dropped on an existing node otherwise it is removed or put back to where it is dragged from
"single" will save the node if dropped on a node with no existing connections otherwise it is removed or put back to where it is dragged from
note - these only work with the currently dragged node - not other multiple selected nodes
deleteNode - (default true) set to false to not allow nodes to be deleted by holding or doubleclicking and delete key
dblclick - (default true) set to false to not allow nodes to be selected by doubleclicking
selected nodes can be moved together
selecting a node selects its children unless the ctrl key is held at which point it will not select children
selected nodes can be deleted with the delete key (or hold to delete)
deleting a node will delete its children
fullMove - (default true) set to false to not automatically drag a node when it is full (if num is set)
min - (default node radius or smallest dimension) the minimum distance from the node's parent a node must move before placing node
max - (default null) the maximum distance from the node's parent a node can be moved to be placed
boundary - (default null) a ZIM Boundary object for the nodes - or a DisplayObject such as the stage (see ZIM Drag)
expand - (default 0 or 10 on mobile) expand the node mousedown area
nodeRollColor - (default node.color.lighten(.2)) the color of the node as rolled over
nodeRollBorderColor - (default node.borderColor) the borderColor of the node as rolled over
nodeSelectedColor - (default white) the selected node color if doubleclicked
nodeSelectedBorderColor - (default node.borderColor) the selected node borderColor if doubleclicked
baseColor - (default node.color) the color of the node connected to a base DisplayObject (see points parameter)
baseBorderColor - (default node.borderColor) the borderColor of the node connected to a base DisplayObject (see points parameter)
baseRollover - (default false) set to true to change all nodes on a base to their roll colors when rolling over the base
rootLock - (default false) do not let the root node (a node in the points array) be draggable or deletable
grandChildren - (default true) do not let there be grandchildren - so there can only be the root nodes and their direct children
dblclickTime - (default .5) time in seconds to capture a double click within (also see ZIM TIME constant)
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
addNode(x, y, base) - add a node at x and y (and on a base) - cannot add nodes in linear mode - see linear parameter
removeNode(node) - remove the node (and its children)
removeConnectors() - removes all nodes and connectors except for root nodes which were specified in the points parameter
selectNode(node, children) - select a node and its children unless children parameter is set to false
addBase(base, baseInfo) - add nodes to a base DisplayObject - see the points parameter for info about the baseInfo
removeBase(base) - remove the connectors for a base - the base will still need to be removed with removeFrom()
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
node - the DisplayObject used to make the connector nodes
the node objects also have these added properties:
creator - the node the node was created from (parent in hierarchy) on null if root node
creatorLine - the line going back to the creator or null if root node
creations - an array of nodes made from the node (its children in hiearchy)
before - the node before it in the original points array (or null if first)
after - the node after it in the original points array (or null if last)
base - the base the node is associated with or null if no base
selected - whether the node is selected or not
orientation - the orientation of the lines from the node
line - the Line object used to make the connector lines
the line objects also have these added properties:
node - a reference to the node at the start of the line
creatorNode - a reference to the node at the end of the line
nodes - the Container that holds the nodes
lines - the Container that holds the lines
points - a read only array of points of node
selectedList - a read-only array of selected nodes
bases - an Array of DisplayObjects used as bases (provided through the points parameter or addBase())
the base objects also have these added properties and methods:
connectors - an array of all connector nodes on the base
connectorMoveEvent - reference to pressmove event on base
connectorUpEvent - reference to pressmove event on base
connectorOverEvent - reference to pressmove event on base
connectorOutEvent - reference to pressmove event on base
setConnectorColors(baseColor, baseBorderColor, nodeRollColor, nodeRollBorderColor) - method to set colors
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "connection" event when a node is made
dispatches a "noconnection" event if a connection is not made
dispatches a "complete" event in linear mode when the connections are complete
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+67.39
zim.Connectors = function(width, height, points, node, line, linear, linearWrap, linearOrder, num, snapH, snapV, dropType, deleteNode, dblclick, fullMove, min, max, boundary, expand, nodeRollColor, nodeRollBorderColor, nodeSelectedColor, nodeSelectedBorderColor, baseColor, baseBorderColor, baseRollover, rootLock, grandChildren, dblclickTime, style, group, inherit) {
var sig = "width, height, points, node, line, linear, linearWrap, linearOrder, num, snapH, snapV, dropType, deleteNode, dblclick, fullMove, min, max, boundary, expand, nodeRollColor, nodeRollBorderColor, nodeSelectedColor, nodeSelectedBorderColor, baseColor, baseBorderColor, baseRollover, rootLock, grandChildren, dblclickTime, style, group, inherit";
var duo; if (duo = zob(zim.Connectors, arguments, sig, this)) return duo;
z_d("67.39");
this.group = group;
var DS = style===false?{}:zim.getStyle("Connectors", this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:null;
if (zot(height)) height = DS.height!=null?DS.height:null;
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Connectors";
if (zot(points)) points = DS.points!=null?DS.points:[[0,0], [100,0], [100,100], [0,100]];
if (zot(node)) node = DS.node!=null?DS.node:new zim.Circle(10, zim.grey, zim.grey);
node.removeFrom(); // in case centerReg() is used
if (node.color == zim.clear && !node.hitArea) node.expand(0);
if (zot(line)) line = DS.line!=null?DS.line:new zim.Line({
length:10,
thickness:3,
color:zim.tin,
strokeObj:{caps:"round"}
});
if (zot(num)) num = DS.num!=null?DS.num:10;
if (zot(linear)) linear = DS.linear!=null?DS.linear:false;
if (zot(linearWrap)) linearWrap = DS.linearWrap!=null?DS.linearWrap:true;
if (zot(nodeRollColor)) nodeRollColor = DS.nodeRollColor!=null?DS.nodeRollColor:node.color.match("rgb")?node.color:node.color.lighten(.2);
if (zot(nodeRollBorderColor)) nodeRollBorderColor = DS.nodeRollBorderColor!=null?DS.nodeRollBorderColor:node.borderColor;
if (zot(nodeSelectedColor)) nodeSelectedColor = DS.nodeSelectedColor!=null?DS.nodeSelectedColor:zim.white;
if (zot(nodeSelectedBorderColor)) nodeSelectedBorderColor = DS.nodeSelectedBorderColor!=null?DS.nodeSelectedBorderColor:node.borderColor;
if (zot(baseColor)) baseColor = DS.baseColor!=null?DS.baseColor:node.color;
if (zot(baseBorderColor)) baseBorderColor = DS.baseBorderColor!=null?DS.baseBorderColor:node.borderColor;
if (zot(baseRollover)) baseRollover = DS.baseRollover!=null?DS.baseRollover:false;
if (zot(min)) min = DS.min!=null?DS.min:node.radius?node.radius*2:Math.min(node.width,node.height);
if (zot(max)) max = DS.max!=null?DS.max:null;
if (zot(expand)) expand = DS.expand!=null?DS.expand:zim.mobile()?10:0;
if (zot(dropType)) dropType = DS.dropType!=null?DS.dropType:"any"; // "any"; // "on", "off" // on is must be on another node, off is must be off other nodes
if (zot(deleteNode)) deleteNode = DS.deleteNode!=null?DS.deleteNode:true;
if (zot(dblclick)) dblclick = DS.dblclick!=null?DS.dblclick:true;
if (zot(fullMove)) fullMove = DS.fullMove!=null?DS.fullMove:true;
if (zot(dblclickTime)) dblclickTime = DS.dblclickTime!=null?DS.dblclickTime:.5;
var timeType = getTIME(dblclickTime);
dblclickTime *= timeType=="s"?1000:1;
if (zot(snapH)) snapH = DS.snapH!=null?DS.snapH:null;
if (zot(snapV)) snapV = DS.snapV!=null?DS.snapV:null;
if (zot(rootLock)) rootLock = DS.rootLock!=null?DS.rootLock:false;
if (zot(grandChildren)) grandChildren = DS.grandChildren!=null?DS.grandChildren:true;
if (linear && points.length <= 1) {
if (zon) zogy("Connector() - linear needs more than one point");
return;
}
var that = this;
that.node = node;
that.line = line;
var nodeColor = node.color;
var nodeBorderColor = node.borderColor;
var offColor = zim.faint; // to reduce edge anti-aliasing
var lines = that.lines = new zim.Container(width, height).addTo(that);
var nodes = that.nodes = new zim.Container(width, height).addTo(that);
if (points.type == "Blob" || points.type == "Squiggle") {
var p = [];
zim.loop(points.points, function (point) {
p.push([point[0], point[1]]);
});
points = p;
}
that.points = points;
this.addNode = function(x, y, base) {
if (linear) return; // cannot add nodes in linear
return addNode(x, y);
};
function addNode (x, y, base, orientation) {
if (x.addChild) {
// adding connector to a base
// second value is a single number for all sides
// or an array of two numbers for left/top and right/bottom
// or an array of four numbers for left,right,top,bottom
// 0 means none, -1 means both corners, -2 means first corner, -3 means second corner
// [box1,3], [box2,[0,3]]
// [[box1,3], [box2,-1]]
// [[box1,[0,3,0,3]], [box2,[3,0,0,3]]] none left top, none right top
// override dropType, rootLock and grandChildren
dropType = "on";
rootLock = true;
grandChildren = false;
base = x;
if (!base.connectorMoveEvent) {
if (!that.bases) that.bases = [];
that.bases.push(base);
base.connectorMoveEvent = base.on("pressmove", function () {
// move all nodes and redraw lines
base.positionConnectors(base, true, true);
});
base.connectorUpEvent = base.on("pressup", function () {
// move all nodes and redraw lines
base.positionConnectors(base, true, true);
});
if (baseRollover) {
base.connectorOverEvent = base.on("mouseover", function () {
addBaseColors(base);
});
base.connectorOutEvent = base.on("mouseout", function () {
removeBaseColors(base);
});
}
base.positionConnectors = function(base, arrowAdjustStart, arrowAdjustEnd) {
zim.loop(base.connectors, function (node) {
var newPoint = base.parent.localToLocal(base.x-base.baseStart.x+node.nodeStart.x, base.y-base.baseStart.y+node.nodeStart.y, node.parent);
node.x = newPoint.x;
node.y = newPoint.y;
drawLines(node, arrowAdjustStart, arrowAdjustEnd);
});
if (base.stage) base.stage.update();
};
base.setConnectorColors = function (color, borderColor, rollColor, rollBorderColor) {
if (!zot(color)) base.connectorColor = color;
if (!zot(borderColor)) base.connectorBorderColor = borderColor;
if (!zot(rollColor)) base.connectorRollColor = rollColor;
if (!zot(rollBorderColor)) base.connectorRollBorderColor = rollBorderColor;
zim.loop(base.connectors, function (node) {
if (!zot(color)) node.color = color;
if (!zot(borderColor)) node.borderColor = borderColor;
});
return base;
};
base.setConnectorColors(baseColor, baseBorderColor, nodeRollColor, nodeRollBorderColor);
}
var baseBounds = base.getBounds();
if (line.endHead)
baseBounds;
if (!Array.isArray(y)) y = [y, y];
var basePoints = [];
if (y.length==2) y = [y[0],y[1],y[0],y[1]];
if (line.lineOrientation == zim.HORIZONTAL || line.lineOrientation == "auto") {
zim.loop([y[0],y[1]], function (data,i) {
if (data==-1 || data==-2) { // top and bottom or or top (side 1)
var top = base.localToLocal(i==0?baseBounds.x:baseBounds.x+baseBounds.width, baseBounds.y, that);
basePoints.push([top.x, top.y, zim.HORIZONTAL]);
}
if (data==-1 || data==-3) { // top and bottom or or top (side 2)
var bot = base.localToLocal(i==0?baseBounds.x:baseBounds.x+baseBounds.width, baseBounds.y+baseBounds.height, that);
basePoints.push([bot.x, bot.y, zim.HORIZONTAL]);
}
if (data > 0) {
zim.loop(data, function (j, t) {
var side = base.localToLocal(i==0?baseBounds.x:baseBounds.x+baseBounds.width, baseBounds.y+baseBounds.height*(j+1)/(t+1), that);
basePoints.push([side.x, side.y, zim.HORIZONTAL]);
});
}
});
}
if (line.orientation == zim.VERTICAL || line.lineOrientation == "auto") {
zim.loop([y[2],y[3]], function (data,i) {
if (data==-1 || data==-2) { // top and bottom or or top (side 1)
var left = base.localToLocal(baseBounds.x, i==0?baseBounds.y:baseBounds.y+baseBounds.height, that);
basePoints.push([left.x, left.y, zim.VERTICAL]);
}
if (data==-1 || data==-3) { // top and bottom or or top (side 2)
var right = base.localToLocal(baseBounds.x+baseBounds.width, i==0?baseBounds.y:baseBounds.y+baseBounds.height, that);
basePoints.push([right.x, right.y, zim.VERTICAL]);
}
if (data > 0) {
zim.loop(data, function (j, t) {
var side = base.localToLocal(baseBounds.x+baseBounds.width*(j+1)/(t+1), i==0?baseBounds.y:baseBounds.y+baseBounds.height, that);
basePoints.push([side.x, side.y, zim.VERTICAL]);
});
}
});
}
base.connectors = [];
base.baseStart = new zim.Point(base.x, base.y);
zim.loop(basePoints, function (point) {
var node = addNode(point[0], point[1], base, point[2]);
addBaseConnector(base, node);
});
setTimeout(function () {
base.positionConnectors(base, true, true);
}, 50);
return that;
} // end base node - then calls addNode again with each one
var theNode = node.clone().loc(x, y, nodes).drag({boundary:boundary}).expand(expand);
theNode.orientation = orientation;
theNode.on("mouseover", overNode);
theNode.on("mouseout", outNode);
theNode.on("mousedown", downNode);
theNode.on("pressmove", moveNode);
theNode.on("pressup", upNode);
if (deleteNode) theNode.hold(holdNode);
theNode.creations = [];
return theNode;
}
// that.added(function () {
function setNodes() {
zim.loop(points, function (point) {
var node = addNode(point[0], point[1]);
});
// for linear, loop through all nodes and give them before and after nodes
if (linear) {
nodes.loop(function (node, i, t) {
if (i==0) {
if (linearWrap) {
node.before = nodes.getChildAt(t-1);
} else {
node.before = null;
}
node.after = nodes.getChildAt(i+1);
} else if (i == t-1) {
if (linearWrap) {
node.after = nodes.getChildAt(0);
} else {
node.after = null;
}
node.before = nodes.getChildAt(i-1);
} else {
node.before = nodes.getChildAt(i-1);
node.after = nodes.getChildAt(i+1);
}
if (linearOrder && i > 0) node.noMouse();
});
}
}
setNodes();
that.keyEvent = function (e) {
if (deleteNode && e.keyCode == 46) { // delete
zim.loop(selectedList, function (obj) {
if (obj && obj.parent) removeNode(obj);
});
if (that.stage) that.stage.update();
}
}
window.addEventListener("keydown", that.keyEvent);
// EVENT FUNCTIONS
function holdNode(e) {
var stage = e.target.stage;
var node = e.target;
if (that.bases || (rootLock && !node.creator.creator)) return;
if (node.adding) removeNode(node.creator);
else removeNode(node);
if (stage) stage.update();
}
function overNode(e) {
var node = e.target;
if (node.selected) return;
node.color = node.base?node.base.connectorRollColor:nodeRollColor;
node.borderColor = node.base?node.base.connectorRollBorderColor:nodeRollBorderColor;
if (that.stage) that.stage.update();
}
function outNode(e) {
var node = e.target;
if (node.selected) return;
node.color = node.base?node.base.connectorColor:nodeColor;
node.borderColor = node.base?node.base.connectorBorderColor:nodeBorderColor;
if (that.stage) that.stage.update();
}
var selectedList = [];
var stagedownID;
var downCount = 0;
var downID;
function downNode(e) {
var child = e.target;
if (!linear && (!rootLock || child.creator) && dblclick) {
if (downCount == 0) {
downID = setTimeout(function () {
downCount = 0;
// also clear the selectedList if not mousing over an object in the selectedList
// as the time for a double click to add an object to the selectedList has expired
if (selectedList) {
var frame = that.stage?that.stage.frame:zdf;
var clearMove = nodes.loop(function (node) {
if (node.hitTestPoint(frame.mouseX, frame.mouseY) && node.selected) return false;
});
if (clearMove) clearselectedList();
}
}, dblclickTime);
}
downCount++;
}
child.startX = child.x;
child.startY = child.y;
if (!linear && selectedList.length > 0) {
zim.loop(selectedList, function (obj) {
obj.startX = obj.x;
obj.startY = obj.y;
});
}
if (child.creations.length >= num || child.selected || (child.creator && !grandChildren)) return;
child.adding = true;
var parent = addNode(child.x, child.y).bot();
// we can't drag a newly created object as the mousedown does not happen on it
// so we could swap the two objects at the pressup
// but this means that all the children of the dragging object would draw lines to the dragging object
// 1. or we can swap all the properties and turn the new object into the parent creator
// and the old object into the child creation
// 2. when we swap, we have to tell its parent that we are swapping
// 3. and we have to tell its children that we are swapping
// 1. swap properties to child so it becomes parent
parent.creations = child.creations;
parent.creatorLine = child.creatorLine;
parent.creator = child.creator;
parent.orientation = child.orientation;
parent.startX = child.startX;
parent.startY = child.startY;
// adjust for bases
if (child.base) {
parent.base = child.base;
parent.baseStart = child.baseStart;
parent.nodeStart = child.nodeStart;
parent.connectors = child.connectors;
child.base = child.baseStart = child.nodeStart = child.connectors = null;
if (parent.base.connectors) parent.base.connectors.splice(parent.base.connectors.indexOf(child), 1, parent);
parent.color = parent.base.connectorColor;
parent.borderColor = parent.base.connectorBorderColor;
}
// adjust to handle linearWrap
parent.before = child.before;
parent.after = child.after;
if (parent.before) parent.before.after = parent;
if (parent.after) parent.after.before = parent;
// 2. tell parent's original parent (creator, if there is one) that its creation has been swapped
if (parent.creator) {
var index = parent.creator.creations.indexOf(child);
if (index != -1) parent.creator.creations.splice(index, 1, parent);
}
// 3. tell parent's children (other creations) that its creator has been swapped
zim.loop(parent.creations, function(creation) {
creation.creator = parent;
});
// set up properties for child
child.creator = parent;
child.creatorLine = line.clone().setPoints(child.x,child.y,child.x,child.y).addTo(lines).alp(0);
child.creatorLine.lineOrientation = child.orientation;
child.creatorLine.node = child;
child.creatorLine.creatorNode = parent;
child.creations = [];
parent.creations.push(child);
}
function moveNode(e) {
var node = e.target;
if (node.creatorLine) node.creatorLine.alp(1);
// if nodes are selected that are not this node being dragged
// then clear the selectedList rather than wait for the clear in the double click timeout
if (!linear && selectedList.length > 0 && selectedList.indexOf(node) == -1) clearselectedList();
drawLines(node, false, true);
if (that.bases) {
zim.loop(that.bases, function (base) {
if (node.creator && node.creator.base == base) return;
if (!base.connectorsOn && node.hitTestBounds(base)) {
addBaseColors(base);
}
if (base.connectorsOn && !node.hitTestBounds(base)) {
removeBaseColors(base);
}
});
}
that.stage.update();
}
function upNode(e) {
var node = e.target;
if (that.bases) {
zim.loop(that.bases, function (base) {
if (base == node.base) return;
if (base.connectorsOn) {
removeBaseColors(base);
}
});
}
var dbl = false;
if (!linear && downCount > 1) { // double click
clearTimeout(downID);
var n = node.adding?node.creator:node;
if (node.adding) removeNode(n.creations[n.creations.length-1]);
if (!n.selected) {
var frame = that.stage?that.stage.frame:zdf;
selectNode(n, !frame.ctrlKey);
}
downCount = 0;
dbl = true;
}
if (!linear && !that.base) {
// test for snap
if (snapH) node.x = Math.round(node.x / snapH)*snapH;
if (snapV) node.y = Math.round(node.y / snapV)*snapV;
}
if ((min && zim.dist(node.x, node.y, node.startX, node.startY) < min) || (max && zim.dist(node.x, node.y, node.startX, node.startY) > max)) {
if (node.adding) {
removeNode(node);
} else {
node.loc(node.startX, node.startY);
if (!dbl) drawLines(node); // drawing twice on double was causing bug
}
that.stage.update();
that.dispatchEvent("noconnection");
return;
}
var complete = false;
var connected = false;
if (linear) {
// must be hitting either active before or after
// must remove target before or after too
var parentNode = node.creator;
that.connectionStart = parentNode;
that.connectionEnd = node;
if (parentNode.before && node.hitTestCircle(parentNode.before) && !linearOrder) {
node.loc(parentNode.before).removeFrom();
parentNode.before.after = null;
if (!parentNode.before.before) parentNode.before.noMouse();
parentNode.before = null;
if (!parentNode.after) parentNode.noMouse();
connected = true;
complete = testComplete();
} else if (parentNode.after && node.hitTestCircle(parentNode.after)) {
node.loc(parentNode.after).removeFrom();
parentNode.after.before = null;
if (!parentNode.after.after) parentNode.after.noMouse();
if (linearOrder) parentNode.after.mouse();
parentNode.after = null;
if (!parentNode.before) parentNode.noMouse();
if (linearOrder) parentNode.noMouse();
connected = true;
complete = testComplete();
} else {
if (!parentNode || node.creations.length > 0) {
node.loc(node.startX, node.startY).bot();
} else {
removeNode(node);
that.stage.update();
that.dispatchEvent("noconnection");
return;
}
}
} else {
if (dropType == "off") { // can't be on a node
var good = nodes.loop(function (obj) {
if (node == obj) return;
if (node.hitTestCircles(obj)) {
if (node.adding) removeNode(node);
else {
node.loc(node.startX, node.startY);
drawLines(node);
}
if (rootLock) checkRootLock(node);
if (!fullMove && node.creator && num > 0 && node.creator.creations.length >= num) node.creator.noMouse();
that.dispatchEvent("connection");
that.stage.update();
return false;
}
});
if (!good) {
noConnect(node);
return;
}
} else if (dropType == "on" || dropType == "single") { // can't be off a node
var hitCount = 0;
var hitObj;
var bad = nodes.loop(function (obj, i, total) {
if (node == obj) return;
if (node.hitTestCircles(obj)) {
hitObj = obj;
if (that.bases && (node.orientation != obj.orientation || (node.creator && node.creator.base && node.creator.base == obj.base))) return;
if (dropType == "on") return false; // bad will be false
hitCount++;
hitCount+=obj.creations.length;
}
});
// loop automatically returns true
if (bad && !(dropType=="single" && hitCount==1)) {
noConnect(node);
return;
} else {
node.loc(hitObj);
// TODO: add more lineType options like a side connector (down/across/up) and an elbow connector (down/up)
// do not let nodes be next to one another sideways
if ((node.creator && node.orientation==zim.VERTICAL && Math.round(node.y) == Math.round(node.creator.startY)) || (node.creator && node.orientation==zim.HORIZONTAL && Math.round(node.x) == Math.round(node.creator.startX))) return;
if (hitObj.base && hitObj.base.connectors) addBaseConnector(hitObj.base, node);
complete = true;
}
}
}
if (!fullMove && node.creator && num > 0 && node.creator.creations.length >= num) node.creator.noMouse();
node.adding = false;
drawLines(node, true, true); // true handles any triangles
zim.loop(selectedList, function (obj) {
obj.startX = obj.x;
obj.startY = obj.y;
});
node.startX = node.x;
node.startY = node.y;
if (rootLock) checkRootLock(node);
if (connected) that.dispatchEvent("connection");
else that.dispatchEvent("noconnection");
if (complete) that.dispatchEvent("complete");
that.stage.update();
}
// HELPER FUNCTIONS
function noConnect(node) {
if (node.adding || !grandChildren) removeNode(node);
else {
node.loc(node.startX, node.startY);
drawLines(node);
}
if (rootLock) checkRootLock(node);
if (node.base && node.base.connectors) removeBaseConnector(node.base, node);
that.stage.update();
that.dispatchEvent("noconnection");
}
function addBaseColors(base) {
zim.loop(base.connectors, function (node) {
node.color = base.connectorRollColor;
node.borderColor = base.connectorRollBorderColor;
});
base.connectorsOn = true;
base.stage.update();
}
function removeBaseColors(base) {
zim.loop(base.connectors, function (node) {
node.color = base.connectorColor;
node.borderColor = base.connectorBorderColor;
});
base.connectorsOn = false;
base.stage.update();
}
// zim.loop(base.connectors, function (node) {
// var newPoint = base.parent.localToLocal(base.x-base.baseStart.x+node.nodeStart.x, base.y-base.baseStart.y+node.nodeStart.y, node.parent);
// node.x = newPoint.x ;
// node.y = newPoint.y ;
// drawLines(node, arrowAdjustStart, arrowAdjustEnd);
// });
function addBaseConnector(base, node) {
base.connectors.push(node);
node.nodeStart = node.parent.localToLocal(node.x, node.y, base.parent);
node.nodeStart.x -= base.x - base.baseStart.x;
node.nodeStart.y -= base.y - base.baseStart.y;
node.base = base;
}
function removeBaseConnector(base, node) {
base.connectors.splice(base.connectors.indexOf(node), 1);
node.nodeStart = null;
node.base = null;
}
function checkRootLock(node) {
if (!node.creator) return;
// stops base from being dragged or doubleClicked
if (node.creator.creator) {
checkRootLock(node.creator);
return;
}
if (node.creator && node.creator.creations.length >= num) node.creator.noMouse();
else node.creator.mouse();
}
function selectNode(n, children) {
if (children) {
zim.loop(n.creations, function (c) {
selectNode(c, children);
});
}
n.selected = true;
n.color = n.base?n.base.connectorColor:nodeSelectedColor;
n.borderColor = n.base?n.base.connectorBorderColor:nodeSelectedBorderColor;
selectedList.push(n);
n.top();
if (!stagedownID) {
stagedownID = that.stage.on("stagemousedown", function (e) {
// test if mouse down on any objects
// would have only cleared if not on any objects in selectedList (selected true)
// but have to wait for the double click to see if we are adding an object to the selectedList
// so final clear if clicking on a non-selectedList node is on the expiry of the double click timeout
// there is also a clearselectedList in the pressmove event
var frame = that.stage?that.stage.frame:zdf;
var clearMove = nodes.loop(function (node) {
if (node.hitTestPoint(frame.mouseX, frame.mouseY)) return false;
});
if (clearMove) clearselectedList();
});
}
}
this.selectNode = function(node, children) {
selectNode(node, children);
};
function testComplete() {
var complete = nodes.loop(function (node) {
if (node.before || node.after) {
return false;
}
});
if (complete) {
nodes.loop(function (node) {
node.noMouse();
});
return true;
}
}
function clearselectedList() {
zim.loop(selectedList, function (obj) {
obj.selected = false;
obj.color = obj.base?obj.base.connectorColor:nodeColor;
obj.borderColor = obj.base?obj.base.connectorBorderColor:nodeBorderColor;
});
selectedList = [];
that.stage.off("stagemousedown", stagedownID);
stagedownID = null;
that.stage.update();
}
function drawLines(node, arrowAdjustStart, arrowAdjustEnd) {
// may have multiple nodes to drag if there is a selectedList
var list = selectedList.length>0?selectedList:[node];
zim.loop(list, function (obj) {
// move other objects to match
if (obj != node) obj.loc(obj.startX+node.x-node.startX, obj.startY+node.y-node.startY);
// draw line back to parent
if (obj.creator) {
obj.creatorLine.setPoints(obj.x, obj.y, obj.creator.x, obj.creator.y, arrowAdjustStart, arrowAdjustEnd);
}
// draw lines to children
zim.loop(obj.creations, function (creation) {
creation.creatorLine.setPoints(creation.x, creation.y, creation.creator.x, creation.creator.y, arrowAdjustStart, arrowAdjustEnd);
});
});
}
function removeNode(node) {
zim.loop(node.creations, function (creation) {
removeNode(creation);
}, true);
if (node.creatorLine) {
node.creatorLine.removeFrom();
var index = node.creator.creations.indexOf(node);
if (index != -1) node.creator.creations.splice(index, 1);
// if dragFull then might have noMoused the creator - so mouse the creator as long as not a base and lockBase
if (!node.creator.mouseEnabled && !(rootLock && !node.creator.creator)) node.creator.mouse();
}
node.removeFrom();
node.removeAllEventListeners();
node = null;
return that;
}
this.removeNode = function(node) {
removeNode(node);
};
function arrive(node) {
// turn all node colors off except for the dragging node
nodes.loop(function (n) {
if (node == n) return;
if (node.type == "Circle") {
if (n.hitTestCircles(node)) n.color = offColor;
} else {
if (n.hitTestBounds(node)) n.color = offColor;
}
});
}
function leave(node) {
// turn all nodes off except one
var set = false;
nodes.loop(function (n) {
if (node == n) return;
if (node.type == "Circle") {
if (n.hitTestCircles(node)) {
if (!set) {
n.color = nodeColor;
set = true;
} else {
n.color = offColor;
}
}
} else {
if (n.hitTestBounds(node)) {
if (!set) {
n.color = nodeColor;
set = true;
} else {
n.color = offColor;
}
}
}
});
}
this.removeConnectors = function() {
zim.loop(nodes, function (node) {
removeNode(node);
}, true);
setNodes();
that.stage.update();
};
this.removeBase = function(base) {
zim.loop(base.connectors, function (node) {
removeNode(node);
});
clearBaseEvents(base);
};
this.addBase = function(base, baseInfo) {
addNode(base, baseInfo);
};
function clearBaseEvents(base) {
base.off("pressmove", base.connectorMoveEvent);
base.off("pressup", base.connectorUpEvent);
if (base.connectorOverEvent) base.off("mouseover", base.connectorOverEvent);
if (base.connectorOutEvent) base.off("mouseout", base.connectorOutEvent);
base.connectors = null;
base.baseStart = null;
base.positionConnectors = base.setConnectorColors = null;
base.connectorColor = base.connectorBorderColor = base.connectorRollColor = base.connectorRollBorderColor = null;
that.bases.splice(that.bases.indexOf(base), 1);
if (that.stage) that.stage.update();
}
Object.defineProperty(this, 'selectedList', {
get: function() {
return selectedList;
},
set: function(value) {
if (zon) zogy("Selectors() - selectedList is read only");
}
});
this.dispose = function(a,b,disposing) {
that.nodes.loop(function (node) {
node.removeFrom();
node.removeAllEventListeners();
node = null;
}, true);
that.lines.loop(function (line) {
line.removeFrom();
line = null;
}, true);
window.removeEventListener("keydown", that.keyEvent);
that.keyEvent = null;
if (that.bases) {
zim.loop(that.bases, function (base) {
clearBaseEvents(base);
});
}
if (!disposing) {
that.zimContainer_dispose(true);
if (that.stage) that.stage.update();
}
return true;
};
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Collectors(width, height, points, node, line, linear, linearWrap, linearOrder, num, snapH, snapV, dropType, deleteNode, dblclick, fullMove, min, max, boundary, expand, nodeRollColor, nodeRollBorderColor, nodeSelectedColor, nodeSelectedBorderColor, baseColor, baseBorderColor, baseRollover, rootLock, grandChildren, dblclickTime, style, that.group, inherit));
};
};
zim.extend(zim.Connectors, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-67.39
/*--
zim.Marquee = function(width, height, items, time, transition, speed, direction, marginLeft, marginRight, marqueeType, borderColor, borderWidth, refresh, mix, style, group, inherit)
Marquee
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A display for ads and promos using an optional ZIM Indicator with pause button.
The Marquee uses the ZIM Pages class to transition multiple items.
The items can be interactive ZIM objects made ahead of time and passed into the items parameters
Images can also be loaded with the load() method
See: https://zimjs.com/marquee.html for an example
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var promo1 = new Container(600, 200);
new Rectangle(promo1.width, promo1.height, yellow).addTo(promo1);
new Circle(30, red).center(promo1).drag();
// could be more
// optionally or alternatively, specify a Marquee object
// there can be multiple image properties using end src as key
// just use null as value if no URL
var marqueeData = {"retina.jpg": ["https://zimjs.com/retina.html", "_blank"]};
var marqueePath = "assets/";
// create Marquee
// note the actual width of marquee will be 25+25 more for added margins (optional)
var marquee = new Marquee(600, 200, [promo1])
.center()
.load(marqueeData, marqueePath);
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 300) width of marquee content
final marquee width will have marginLeft and marginRight added to this width
height - (default 100) height of content and marquee
items - default(null) an array of Display Objects - can be interactive
time - default(5) time interval in seconds for changing items (also see ZIM TIME constant)
also see marqueeTime property for each item to individually override the time for viewing
transition - default("slide") the transition between items
options are: "none", "reveal", "slide", "fade", "clear", "black", "white", "fan"
speed - default(.5) speed of transition in seconds (also see ZIM TIME constant)
direction - default("right") location of next item relative to current item
options are: "right", "left", "up", "down"
marginLeft - default(25) width at left of content for Indicator and Pause button
set to 0 to not show indicator and pause button
marginRight - default(25) width at right of content for Z logo with animated MARQUEE
set to 0 to not show Z logo with animated MARQUEE
marqueeType - (default "dot" or "circle") the Indicator type - also "box" or "square"
borderColor - (default "#333") border color - any ZIM or HTML color - set to -1 for no border
borderWidth - (default 1) width of border if borderColor - set to 0 for no border
refresh - (default 30*60 seconds) page refresh to handle browser memory build
mix - (default true) randomize content and then play in that order - different for each page load
note: loaded files will always come after initial marquee items
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
add(obj, url, target) - add a Display Object (obj) - can be interactive content - returns obj for chaining
can provide an overall url and target for url
but often will provide navigation button, etc. as part of interactive content
remove(obj) - remove an object from the marquee - returns obj for chaining
will also call a dispose() method on the obj if there is one
go(page) - transition to specific page (obj) or index - returns obj for chaining
pause(state, immediate) - pause or unpause the Marquee - returns obj for chaining
can be used by interactive code to pause Marquee when interacting
immediate (default false) set to true to make the Marquee go to next item right away when unpausing (no effect when pausing)
load(data, path) - Marquee object for images their optional action url and target: - returns obj for chaining
data in format: {imageSrc:"actionURL", imageSrc:["actionURL", "target"], etc.}
path: optional directory location such as a relative path: "assets/"
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
content - a reference to the ZIM Container that holds the content
pages - a reference to the ZIM Pages object that holds the items
use pages.pages to access an array of pages, etc. - see Pages Class
button - a reference to the pause/play button if there is one
indicator - a reference to the ZIM Indicator if there is one - see Indicator Class
selectedIndex - the selected index of the Marquee
selected - the selected item of the Marquee
lastSelected - the last selected item of the Marquee
time - get or set the time of the marquee (between changing items)
speed - get the speed of the transition
paused - read only property as to whether the Marquee is paused - see pause() method
interval - a reference to the ZIM interval
left - a reference to the left Container
right - a reference to the right Container if there is one
icon - a reference to the Z icon if there is one
label - a reference to the MARQUEE Label that pops out of the Z if there is one
eg. label.visible = false to not show label popping out
marqueeLoader - a reference to the ZIM loadAssets queue if load() is used
Each item gets a marquee property that points to the ZIM marquee it is in
Each item gets a marqueViews property recording how many times viewed
Each item can have a marqueeTime property set to ms to customize its view time
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "page" event when item starts to change
dispatches a "pagetransitioned" event when item finishes changing
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+67.4
zim.Marquee = function(width, height, items, time, transition, speed, direction, marginLeft, marginRight, marqueeType, borderColor, borderWidth, refresh, mix, style, group, inherit) {
var sig = "width, height, items, time, transition, speed, direction, marginLeft, marginRight, marqueeType, borderColor, borderWidth, refresh, mix, style, group, inherit";
var duo; if (duo = zob(zim.Marquee, arguments, sig, this)) return duo;
z_d("67.4");
this.group = group;
var DS = {};
var DS = style===false?{}:zim.getStyle("Marquee", this.group, inherit);
var that = this;
if (zot(width)) width = DS.width!=null?DS.width:300;
if (zot(height)) height = DS.height!=null?DS.height:100;
var timeType = getTIME(time);
if (zot(time)) time = DS.time!=null?DS.time:timeType=="s"?5:5000;
if (zot(transition)) transition = DS.transition!=null?DS.transition:"slide";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"#333";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:1;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(marginLeft)) marginLeft = DS.marginLeft!=null?DS.marginLeft:25;
if (zot(marginRight)) marginRight = DS.marginRight!=null?DS.marginRight:25;
if (zot(speed)) speed = DS.speed!=null?DS.speed:timeType=="s"?.5:500;
checkTIME(speed, timeType);
if (zot(direction)) direction = DS.direction!=null?DS.direction:"right";
if (zot(refresh)) refresh = DS.refresh!=null?DS.refresh:timeType=="s"?30*60:30*60*1000; // 30 minutes
if (zot(mix)) mix = DS.mix!=null?DS.mix:true;
this.zimContainer_constructor(width+marginLeft+marginRight,height,null,null,false);
this.type = "Marquee";
this.speed = speed;
var mask = new zim.Rectangle(width-1,height-1,zim.clear).addTo(that).mov(marginLeft+.5, .5);
var content = this.content = new zim.Container(width, height)
.loc(marginLeft,0,that)
.setMask(mask);
var pages = this.pages = new zim.Pages(null, transition, speed, null, content).addTo(content);
var startCheck = false;
this.add = function(obj, url, target, skip, center) {
if (zot(center)) center = true;
obj.scaleTo(content);
if (url) obj.cur().on("click", function() {
zgo(url, target);
});
pages.addPage(obj);
if (center) pages.center();
obj.marqueeViews = 0;
obj.marquee = that;
if (!startCheck) startSelection();
if (!skip) makeIndicator();
if (border) border.top();
};
this.remove = function(obj) {
if (that.selected == obj) {
if (that.pages.pages.length == 1) return;
var newIndex = that.selectedIndex+1;
if (newIndex == that.pages.pages.length) newIndex = 0;
that.pages.go(newIndex,null,null,0);
setTimeout(function () {
that.pages.removePage(obj);
if (obj.dispose) obj.dispose();
makeIndicator();
}, 20);
} else {
that.pages.removePage(obj);
if (obj.dispose) obj.dispose();
makeIndicator();
}
};
function startSelection() {
startCheck = true;
that.selectedIndex = 0;
that.selected = pages.pages[that.selectedIndex].page;
that.lastSelected = null;
if (that.selected.marqueeOn) that.selected.marqueeOn();
that.interval = zim.interval(time, function () {
that.go();
});
}
if (!zot(items) && !Array.isArray(items)) items = [items];
if (items && items.length > 0) {
if (mix) zim.shuffle(items);
zim.loop(items, function (item) {
that.add(item, null, null, true); // don't make indicator
});
}
if (refresh > 0) var to = zim.timeout(refresh*(timeType=="s"?1000:1), function(){
location.reload();
}, null, "ms");
that.go = function(page) {
that.selected.marqueeViews+=1;
if (that.selected.marqueeOff) that.selected.marqueeOff();
if (page) {
that.selected = page;
zim.loop(pages.pages, function (p,i) {
if (p.page==page) {
that.selectedIndex = i;
return;
}
});
that.interval.interval = that.selected.marqueeTime ? that.selected.marqueeTime : time;
that.interval.pause(pause.toggled, null, true); // reset time
} else {
var next = that.selectedIndex+1;
that.selectedIndex = next%pages.pages.length;
that.selected = pages.pages[that.selectedIndex].page;
that.interval.time = that.selected.marqueeTime ? that.selected.marqueeTime : time;
}
that.dispatchEvent("page");
if (that.selected.marqueeOn) that.selected.marqueeOn();
pages.go(that.selected, direction, transition, speed);
};
pages.on("pagetransitioned", function () {
that.dispatchEvent("pagetransitioned");
if (that.indicator) that.indicator.selectedIndex = that.selectedIndex;
});
// ~~~~~~~~~~~~
// LEFT
var _paused = false;
var left = that.left = new zim.Container(marginLeft-4,height-4);
var pauseIcon = new zim.Shape().sca(.6);
pauseIcon.graphics.f(zim.light).mt(0,0).p("AAhCLIAAkVIBXAAIAAEVgAh3CLIAAkVIBXAAIAAEVg");
var playIcon = new zim.Shape().sca(.6).reg(-2,0);
playIcon.graphics.f(zim.light).mt(0,0).p("AiJieIETCeIkTCfg");
var pause = that.button = new zim.Button({
label:"",
icon:pauseIcon,
toggleIcon:playIcon,
width:45,
height:45,
corner:0,
shadowBlur:0
})
.scaleTo(left, 100)
.pos(0,0,false,true,left);
pause.on("click", function () {
if (that.interval) that.interval.pause(pause.toggled);
_paused = pause.toggled;
that.stage.update();
});
var prop;
function makeIndicator() {
if (zot(marginLeft) || marginLeft==0) return;
var gutterLeft = 4*marginLeft/25;
left.pos((marginLeft-left.width)-gutterLeft,gutterLeft/2,false,true,that);
if (that.indicator) {
that.indicator.dispose();
that.indicator.removeFrom();
}
if (!prop) prop = new zim.Proportion(8,16,left.width+gutterLeft,left.width/2+gutterLeft,-1);
that.indicator = new zim.Indicator({
width:(pages.pages.length<=2?pages.pages.length:pages.pages.length-1)*(left.width-3),
height: prop.convert(pages.pages.length),
num: pages.pages.length,
shadowBlur:-1,
interactive:true,
scale:1.2,
indicatorType:marqueeType
});
that.indicator.fit(0,0,height-pause.height,pause.width);
that.indicator.rot(direction=="down"?-90:90)
.center(left)
.pos(null,left.width-gutterLeft/2,null,true);
that.indicator.selectedIndex = that.selectedIndex;
that.indicator.on("change", function () {
that.go(pages.pages[that.indicator.selectedIndex].page);
});
}
makeIndicator();
// ~~~~~~~~~~~~~
// RIGHT
if (!zot(marginRight) && marginRight>0 && typeof zdf != "undefined" && zdf) {
var gutterRight = 4*marginRight/25;
var right = that.right = new zim.Container(45,270);
var icon = that.icon = zdf.makeIcon(zim.grey, zim.lighter, zim.silver)
.sca(.5)
.pos(0,0,true,true,right)
.mov(0,0)
.cur();
// .sha(white,0,1,1);
icon.on("mouseover", function () {
lab.animate({props:{scaleX:1}, time:500, ease:"backOut", override:true, timeUnit:"ms"});
icon.stage.update();
});
icon.on("mouseout", function () {
lab.animate({props:{scaleX:0}, time:300, ease:"backIn", override:true, timeUnit:"ms"});
icon.stage.update();
});
icon.on("mousedown", function () {
zgo("https://zimjs.com/marquee", "_blank");
});
var lab = that.label = new zim.Label({
text:"MARQUEE",
color:zim.dark,
backgroundColor:zim.lighter,
shiftVertical:1,
paddingVertical:5
})
.rot(-90)
.pos(0,13,true,false,right)
.reg(-10)
.sca(0,1)
.mov(0);
right.fit(0,0,marginRight-gutterRight,height-gutterRight);
right.pos(marginRight-right.width-gutterRight,gutterRight/2,true,true,that);
}
if (that.stage) that.stage.update();
this.pause = function(state, immediate) {
if (zot(state)) state = true;
if (state == _paused) return;
_paused = state;
that.interval.pause(state, immediate);
that.button.toggle(state);
};
Object.defineProperty(this, 'paused', {
get: function() {
return _paused;
},
set: function(value) {
if (zon) zogy("Marquee() - paused is read only - use pause()");
}
});
Object.defineProperty(this, 'time', {
get: function() {
return time;
},
set: function(value) {
time = value;
that.interval.time = time;
}
});
this.load = function(data, path) {
// Load any marqueeAssets with lazy loading
var a = []; // make an array of only the asset urls
if (mix) zim.shuffle(data);
zim.loop(data, function(asset) {
if (Array.isArray(asset)) a.push(asset[0]); // could have target window
else a.push(asset);
});
var frame = that.stage?that.stage.frame:zdf;
that.marqueeLoader = frame.loadAssets(a, path);
that.loadEvent = that.marqueeLoader.on("assetload", function (e) {
var d = data[e.asset.id];
if (Array.isArray(d)) {
var u = d[0];
var t = d[1];
} else {
var u = d;
var t = "_self";
}
that.add(e.asset, u, t);
makeIndicator();
});
return that;
};
if (!zot(borderColor)) {
var border = new zim.Rectangle(width-1, height-1, zim.clear, borderColor, borderWidth).loc(mask,null,that);
border.mouseEnabled = false;
}
if (style!==false) zim.styleTransforms(this, DS);
this.clone = function() {return that.cloneProps(new zim.Marquee(width, height, items, time, transition, speed, direction, marqueeType, borderColor, borderWidth, refresh, mix, style, this.group, inherit));};
this.dispose = function (a,b,disposing) {
if (to) to.clear();
if (that.interval) that.interval.clear();
if (that.loadEvent) that.marqueeLoader.off("assetload", that.loadEvent);
pages.dispose();
pages = null;
if (!disposing) this.zimContainer_dispose(true);
return true;
};
};
zim.extend(zim.Marquee, zim.Container, ["clone", "dispose"], "zimContainer");
//-67.4
/*--
zim.Loader = function(width, height, label, type, backgroundColor, rollBackgroundColor, color, rollColor, borderColor, borderWidth, corner, shadowColor, shadowBlur, hitPadding, gradient, gloss, dashed, backing, rollBacking, rollPersist, icon, rollIcon, toggle, toggleBacking, rollToggleBacking, toggleIcon, rollToggleIcon, toggleEvent, frame, multiple, accept, style, group, inherit)
Loader
zim class - extends a zim.Button which extends a zim.Container
DESCRIPTION
Loader lets you upload images, text or JSON. These are available on the loaded event function.
Loader uses the HTML input type=file tag and overlays this with a createjs DOMElement.
Loader is a Button so can be displayed for the user to click on.
It defaults to a dashed line region as you can also drag and drop files to the loader.
You can also save an image using the save() method to a new browser window for the user to save
NOTE: due to the HTML tag being overlayed, the loader.resize() must be called if it is moved
(This is called automatically when the stage is resized)
NOTE: if the loader is placed in a container and the container is removed or added again
the loader must be manually removed or added again with loader.removeFrom() or loader.addTo().
This is so ZIM does not have to keep track of HTML tags each time a container is added or removed.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var loader = new Loader({
frame:frame,
label:"UPLOAD PIC OR DROP PICS HERE",
width:700,
height:400,
corner:50
}).center();
loader.on("loaded", function(e) {
loop(e.bitmaps, function(bitmap){
bitmap.centerReg().drag();
});
loader.removeFrom(stage);
stage.update();
});
// and to later save for instance in a button event:
saveButton.on("click") {
loader.save(stage); // or some other container... can specify crop bounds too
}
END EXAMPLE
EXAMPLE
// loading a JSON file:
var loader = new Loader({
frame:frame,
type:"JSON",
label:"UPLOAD JSON",
width:700,
height:400,
corner:50
}).center();
// choose a test.json file with the following in it:
// {"test":"testing"}
loader.on("loaded", function(e) {
zog(e.json.test); // "testing"
loader.removeFrom();
stage.update();
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 250) the width of the button
height - (default 70) the height of the button
label - (default "UPLOAD PIC") ZIM Label or plain text
type - (default "image") set to "text" to receive text or "JSON" to receive a parsed JSON file
backgroundColor - (default "rgba(0,0,0,.05)") background color of button (any CSS color)
rollBackgroundColor - (default "rgba(0,0,0,.1)") rollover color of button backbground
color - (default "rgba(0,0,0,.5)") text color of button (any CSS color)
rollColor - (default color) rollover text color of button
borderColor - (default rgba(0,0,0,.3)) the color of the border
borderWidth - (default 1) thickness of the border
corner - (default 0) the round of the corner (set to 0 for no corner)
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
shadowColor - (default "rgba(0,0,0,.3)") set to -1 for no shadow
shadowBlur - (default 14) how blurred the shadow is if the shadow is set
hitPadding - (default 0) adds extra hit area to the button (good for mobile)
gradient - (default 0) 0 to 1 (try .3) adds a gradient to the button
gloss - (default 0) 0 to 1 (try .1) adds a gloss to the button
backing - (default null) a Display object for the backing of the button (eg. Shape, Bitmap, Container, Sprite)
see ZIM Pizzazz module for a fun set of Button Shapes like Boomerangs, Ovals, Lightning Bolts, etc.
https://zimjs.com/bits/view/pizzazz.html
rollBacking - (default null) a Display object for the backing of the rolled-on button
rollPersist - (default false) set to true to keep rollover state when button is pressed even if rolling off
icon - (default false) set to display object to add icon at the center of the button and remove label
https://zimjs.com/bits/view/icons.html
rollIcon - (default false) set to display object to show icon on rollover
toggle - (default null) set to string to toggle with label or display object to toggle with icon or if no icon, the backing
rollToggle - (default null) set to display object to toggle with rollIcon or rollBacking if no icon
there is no rollToggle for a label - that is handled by rollColor on the label
toggleEvent - (default mousedown for mobile and click for not mobile) what event causes the toggle
dashed - (default true) set to false to turn off the dashed for the border
frame - (default the zdf) a reference to the Frame (to scale and position the HTML tag)
multiple - (default true) set to false to let user only upload one file rather than multiple files (with shift or ctrl)
accept - (default null) set to extension / MIME-type to limit types of files the upload dialog will suggest
here are some examples:
"image/*"
"image/jpeg, image/png"
".png, .jpeg, .jpg, .gif"
"image/jpeg, .jpeg, .jpg"
".txt, .json, application/json"
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
resize() - call the resize event if the scale or position of the Loader is changed
this will sync the location of the HTML input tag
resize() is only needed if the scale or x, y of the Loader (or its container) is changed
it is not needed for general window resizing - the Loader handles this
Note: if the Frame itself changes location in the HTML document, call a frame.update()
this will then dispatch an update event to the Loader and it will resize()
this is not needed if resizing the window or scrolling - see Frame update() method docs
save(content, filename, x, y, width, height, cached, cachedBounds, type, data) - save a picture (supports ZIM DUO)
content - the Display object to be saved such as a Container, Bitmap, etc.
filename - (default random) - the text name of the file (with or without extension - also see type)
x, y, width, height - the cropping bounds on that object otherwise defaults to 0,0,stageW,stageH
cached - (default false) set to true if the object is currently already cached
cachedBounds - if you are saving a different bounds than was previously cached
setting the bounds here (createjs.Rectangle) will restore the cache to the previous bounds
type - (default "png") set to "jpeg" for jpeg
data - (default false) set to true to save as base64 data
otherwise save returns the object for chaining
quality - (default .92) a number between 0 an 1 representing the quality of the saved image (jpeg)
note, this parameter may be moved to before data in the next version of ZIM
Button methods:
setBacking(type, newBacking) - dynamically set any type of backing for button (if null removes backing for that type)
Backing types are: "backing", "rollBacking", "toggleBacking", "rollToggleBacking", "waitBacking", "rollWaitBacking"
note - all backing will have a pattern property if a pattern is set as a backing
setIcon(type, newIcon) - dynamically set any type of icon for button (if null removes icon for that type)
Icon types are: "icon", "rollIcon", "toggleIcon", "rollToggleIcon", "waitIcon", "rollWaitIcon"
toggle(state) - forces a toggle of label if toggle param is string, else toggles icon if icon is set or otherwise toggles backing
state defaults to null so just toggles
pass in true to go to the toggled state and false to go to the original state
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: see the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
tag - the HTML input tag of type file - used for uploading
frame - get or set the frame - set this if changing frames
Button properties:
text - references the text property of the Label object of the button
label - gives access to the label
backgroundColor - get or set non-rolled on backing color (if no backing specified)
rollBackgroundColor - get or set rolled on backing color
color - get or set non-rolled on text color (if no icon specified)
rollColor - get or set rolled on text color
backing - references the backing of the button
rollBacking - references the rollBacking (if set)
icon - references the icon of the button (if set)
rollIcon - references the rollIcon (if set)
toggleObj - references the toggle object (string or display object if set)
rollToggle - references the rollToggle (if set)
toggled - true if button is in toggled state, false if button is in original state
enabled - default is true - set to false to disable
rollPersist - default is false - set to true to keep rollover state when button is pressed even if rolling off
focus - get or set the focus property of the Button used for tabOrder
ALSO: see ZIM Container for properties such as:
width, height, widthOnly, heightOnly, draggable, level, depth, group
blendMode, hue, saturation, brightness, contrast, etc.
ALSO: see the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
loaded - is dispatched when the files(s) are uploaded - the event object comes with the following properties:
FOR IMAGES (see types array)
e.bitmaps - an array of Bitmap objects of the loaded images
e.bitmap - the first Bitmap to be created from the loaded images
e.lastBitmap - the last Bitmap to be created from the loaded images
e.total - the total Bitmap objects to be created from the loaded images
FOR TEXT (see types array)
e.texts - an array of String objects of the loaded text files
e.text - the first text loaded
e.lastText - the last text loaded
e.total - the total number of texts loaded
FOR JSON (see types array)
e.jsons - an array of JSON objects of the loaded JSON files
e.json - the first JSON object loaded
e.lastJSON - the last JSON object loaded
e.total - the total number of JSON files loaded
ALSO: see the CreateJS Easel Docs for Container events such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
--*///+67.5
zim.Loader = function(width, height, label, type, backgroundColor, rollBackgroundColor, color, rollColor, borderColor, borderRollColor, borderWidth, corner, shadowColor, shadowBlur, hitPadding, gradient, gloss, dashed, backing, rollBacking, rollPersist, icon, rollIcon, toggle, toggleBacking, rollToggleBacking, toggleIcon, rollToggleIcon, toggleEvent, frame, multiple, accept, style, group, inherit) {
var sig = "width, height, label, type, backgroundColor, rollBackgroundColor, color, rollColor, borderColor, borderRollColor, borderWidth, corner, shadowColor, shadowBlur, hitPadding, gradient, gloss, dashed, backing, rollBacking, rollPersist, icon, rollIcon, toggle, toggleBacking, rollToggleBacking, toggleIcon, rollToggleIcon, toggleEvent, frame, multiple, accept, style, group, inherit";
var duo; if (duo = zob(zim.Loader, arguments, sig, this)) return duo;
z_d("67.5");
this.group = group;
var DS = style===false?{}:zim.getStyle("Loader", this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:250;
if (zot(height)) height = DS.height!=null?DS.height:70;
if (zot(type)) type = DS.type!=null?DS.type:"image";
type = type.toLowerCase();
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"rgba(0,0,0,.05)";
if (zot(rollBackgroundColor)) rollBackgroundColor = DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"rgba(0,0,0,.1)";
if (zot(color)) color = DS.color!=null?DS.color:"rgba(0,0,0,.5)";
if (zot(rollColor)) rollColor = DS.rollColor!=null?DS.rollColor:color;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"rgba(0,0,0,.3)";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:1;
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:true;
if (zot(corner)) corner = DS.corner!=null?DS.corner:0;
if (zot(multiple)) multiple = DS.multiple!=null?DS.multiple:true;
if (zot(label)) label = DS.label!=null?DS.label:new zim.Label({
text:"UPLOAD PIC", color:color, rollColor:rollColor, valign:"center", align:"center",
backing:"ignore", shadowColor:"ignore", shadowBlur:"ignore", backgroundColor:"ignore",
group:this.group
});
if (zot(frame)) {
if (zdf) {
frame = zdf;
} else {
if (zon) {zog("zim.Loader - please provide a reference to zim Frame");} return;
}
}
// this.zimButton_constructor();
this.zimButton_constructor(width, height, label, backgroundColor, rollBackgroundColor, color, rollColor, borderColor, borderRollColor, borderWidth, corner, shadowColor, shadowBlur, hitPadding, gradient, gloss, dashed, backing, rollBacking, rollPersist, icon, rollIcon, toggle, null, null, null, null, toggleBacking, rollToggleBacking, toggleIcon, rollToggleIcon, toggleEvent, null, null, null, null, null, null, null, null, null, null, null, null, false);
this.type = "Loader";
var that = this;
var stage = frame.stage;
label = that.label;
var uploadTag = that.tag = document.createElement("input");
document.body.appendChild(uploadTag);
uploadTag.setAttribute("type", "file");
uploadTag.setAttribute("aria-hidden", true);
if (multiple) uploadTag.setAttribute("multiple", "multiple");
if (accept) uploadTag.setAttribute("accept", accept);
uploadTag.hidden = true;
uploadTag.zimDisplay = uploadTag.style.display || "inline-block";
uploadTag.style.cssText = "border:thin solid grey; z-index:2; width:" + width + "px; height:" + height + "px; overflow:hidden; outline:none;"
+ "position:absolute; left:0px; top:0px; display:none; cursor:pointer; opacity: 0; filter: alpha(opacity=0);";
this.addEventListener('mousedown', function() { // added for zim.Accessibility
uploadTag.click();
});
uploadTag.addEventListener('change', handleFile);
var upload = new createjs.DOMElement(uploadTag);
stage.addChild(upload);
upload.alpha = 0;
var pRatio = frame.retina?(window.devicePixelRatio || 1):1;
var time1;
var time2;
this.resize = function() {
if (!that.stage) {
uploadTag.setAttribute("aria-hidden", true);
uploadTag.hidden = true;
uploadTag.style.display = "none";
// uploadTag.previosSibling.hidden = true;
// uploadTag.previosSibling.style.display = "none";
return;
}
uploadTag.setAttribute("aria-hidden", false);
uploadTag.hidden = false;
uploadTag.style.display = uploadTag.zimDisplay;
// uploadTag.previosSibling.hidden = false;
// uploadTag.previosSibling.style.display = "block";
time1 = setTimeout(function() {
var displayProps = that.getConcatenatedMatrix().decompose();
var point = that.localToGlobal(0, 0);
if (frame.retina) {
upload.x = frame.x/stage.scaleX + point.x/pRatio;
upload.y = frame.y/stage.scaleY + point.y/pRatio;
// CreateJS DOMElement is scaling tag as stage scales
zim.sca(upload, displayProps.scaleX/pRatio/stage.scaleX, displayProps.scaleY/pRatio/stage.scaleY);
} else {
upload.x = frame.x + point.x * frame.scale;
upload.y = frame.y + point.y * frame.scale;
zim.sca(upload, frame.scale*displayProps.scaleX, frame.scale*displayProps.scaleY);
}
stage.update();
}, 50);
return that;
};
this.resize();
that.on("added", function() {
uploadTag.style.display = "block";
uploadTag.hidden = false;
uploadTag.style.display = "block";
that.resize();
});
that.added(addedCallback);
function addedCallback() {
that.resize();
time2 = setTimeout(function() {
uploadTag.style.display = "block";
uploadTag.hidden = false;
uploadTag.style.display = "block";
}, 50);
that.on("added", addedCallback, null, true); // once
}
that.on("removed", function() {
if (time1) clearTimeout(time1);
if (time2) clearTimeout(time2);
if (uploadTag) {
uploadTag.style.display = "none";
uploadTag.hidden = true;
uploadTag.style.display = "none";
}
});
function handleFile(e) {
var files;
if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
files = e.dataTransfer.files;
} else {
files = e.target.files;
}
if (type=="text" || type=="json") {
var texts = [];
var firstText;
var lastText;
if (type.toLowerCase()=="json") {
var jsons = [];
var firstJSON;
var lastJSON;
}
} else {
var bitmaps = [];
var firstBitmap;
var lastBitmap;
}
for (var i=0; isaved