For dark websites, you can use this button. This button is circular in shape. As you can see, this button has a white border and no background. The information icon is located on the button. Is displayed by clicking on the pop-up button. To display the pop-up, first the button moves to the middle of the page and then the pop-up is displayed.
<!-- This script got from frontendfreecode.com -->
<div id="app"></div><a style="font-size: 8pt; text-decoration: none" target="_blank" href="http://frontendfreecode.com">Free Frontend</a>
@charset "UTF-8";
html {
box-sizing: border-box;
background-color: #2d3437;
font-size: 62.5%;
font-family: Roboto, Helvetica, sans-serif;
overflow: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
*, *::before, *::after {
box-sizing: inherit;
}
html, body {
height: 100%;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
#app {
display: flex;
flex: 1 1 auto;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.morph-button-to-modal-wrapper {
position: relative;
overflow: visible;
top: 80vh;
left: 10vw;
width: 3.2rem;
height: 3.2rem;
}
.morph-button-to-modal {
position: relative;
top: 0;
bottom: 0;
overflow: hidden;
min-width: 3.2rem;
min-height: 3.2rem;
width: 3.2rem;
max-height: 3.2rem;
border: 0.2rem solid #fff;
border-radius: 50%;
background: transparent;
color: #fff;
will-change: content, width, max-width, max-height, transform;
transition-property: width, max-width, max-height, border-color, border-radius, background-color;
transition-duration: 350ms, 350ms, 350ms, 200ms, 200ms, 400ms;
transition-timing-function: cubic-bezier(0.46, 0.03, 0.52, 0.96);
transition-delay: 100ms, 100ms, 200ms, 400ms, 400ms, 200ms;
}
.morph-button-to-modal.open {
z-index: 1000;
width: 90rem;
max-width: calc(100vw - 2rem);
max-height: calc(100vh - 2rem);
border-color: transparent;
border-radius: 1rem;
background-color: #394144;
transition-delay: 200ms, 200ms, 200ms, 200ms, 200ms, 200ms;
}
.morph-button-to-modal button {
appearence: none;
background: none;
border: none;
padding: 0;
}
.morph-button-to-modal .morph-button-enter {
opacity: 0.01;
}
.morph-button-to-modal .morph-button-enter.morph-button-enter-active {
opacity: 1;
transition-property: opacity;
transition-duration: 300ms;
transition-timing-function: ease-out;
transition-delay: 400ms;
}
.morph-button-to-modal .morph-button-leave {
opacity: 1;
}
.morph-button-to-modal .morph-button-leave.morph-button-leave-active {
opacity: 0;
transition: opacity 200ms ease-out;
}
.morph-button-to-modal .morph-modal-enter {
opacity: 0.01;
}
.morph-button-to-modal .morph-modal-enter.morph-modal-enter-active {
opacity: 1;
transition-property: opacity 320ms ease-out 500ms;
}
.morph-button-to-modal .morph-modal-leave {
opacity: 1;
}
.morph-button-to-modal .morph-modal-leave.morph-modal-leave-active {
opacity: 0;
transition: opacity 200ms ease-out;
}
.morph-button-to-modal .morph-button {
position: absolute;
width: 100%;
height: 100%;
}
.morph-button-to-modal .morph-modal-container {
display: flex;
flex-flow: column nowrap;
align-items: stretch;
position: relative;
padding: 2rem;
}
.morph-button-to-modal .morph-modal-title {
flex: 0 0 auto;
overflow: hidden;
padding-bottom: 2rem;
border-bottom: 0.1rem solid #545e61;
font-size: 2rem;
font-weight: 500;
white-space: nowrap;
text-overflow: ellipsis;
}
.morph-button-to-modal .btn-close {
position: absolute;
top: 1.4rem;
right: 2rem;
color: #b0b5b8;
font-size: 2.4rem;
}
.morph-button-to-modal .morph-modal-body {
flex: 0 1 auto;
overflow-y: auto;
max-height: calc(100vh - 14rem);
font-size: 1.5rem;
}
.device-entry-info-modal .morph-modal-enter .device-details-info > * {
border-color: transparent;
}
.device-entry-info-modal .morph-modal-enter .device-details-info > * > * {
opacity: 0.01;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * {
border-left-color: #545e61;
transition: border-color 250ms ease-in 500ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > * {
opacity: 1;
transition: opacity 300ms ease-in 420ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(1) {
transition-delay: 452ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(2) {
transition-delay: 484ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(3) {
transition-delay: 516ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(4) {
transition-delay: 548ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(5) {
transition-delay: 580ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(6) {
transition-delay: 612ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(7) {
transition-delay: 644ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(8) {
transition-delay: 676ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(9) {
transition-delay: 708ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(10) {
transition-delay: 740ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(11) {
transition-delay: 772ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(12) {
transition-delay: 804ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(13) {
transition-delay: 836ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(14) {
transition-delay: 868ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(15) {
transition-delay: 900ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(16) {
transition-delay: 932ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(17) {
transition-delay: 964ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(18) {
transition-delay: 996ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(19) {
transition-delay: 1028ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(20) {
transition-delay: 1060ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(21) {
transition-delay: 1092ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(22) {
transition-delay: 1124ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(23) {
transition-delay: 1156ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(24) {
transition-delay: 1188ms;
}
.device-entry-info-modal .modal-button {
font-size: 3.2rem;
}
.device-entry-info-modal .info-key-value {
display: flex;
justify-content: space-between;
white-space: nowrap;
line-height: 2.5;
}
.device-entry-info-modal .info-key-value, .device-entry-info-modal .info-key-value .info-key, .device-entry-info-modal .info-key-value .info-value {
margin: 0;
}
.device-entry-info-modal .info-key-value .info-key {
flex: 0 1 auto;
overflow: hidden;
padding-right: 1em;
color: #fff;
font-weight: 600;
text-overflow: ellipsis;
}
.device-entry-info-modal .info-key-value .info-value {
flex: 0 0 auto;
text-align: right;
color: #b0b5b8;
}
.device-entry-info-modal .device-details-info {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
width: 100%;
max-width: 100%;
margin: 3rem 0;
}
.device-entry-info-modal .device-details-info > * {
flex: 0 1 33.33333%;
max-width: 33.33333%;
padding: 0 3rem;
border-left: 0.1rem solid #545e61;
}
.device-entry-info-modal .device-details-info > *:first-of-type {
border: none;
padding-left: 0;
}
.device-entry-info-modal .device-details-info > *:last-of-type {
padding-right: 0;
}
.device-entry-info-modal .sub.info-key::before {
content: "↳";
margin-right: 0.5em;
font-family: sans-serif;
color: #b0b5b8;
}
.device-entry-info-modal .device-details-info-header {
display: flex;
flex-flow: row nowrap;
align-content: center;
margin-bottom: 4rem;
padding: 2.4rem 0 1.8rem;
border-bottom: 0.1rem solid #545e61;
}
.device-entry-info-modal .device-details-info-header .device-image {
margin-right: 2.8rem;
color: #36d3b4;
font-size: 6.4rem;
}
.device-entry-info-modal .device-details-info-header .device-name, .device-entry-info-modal .device-details-info-header .device-online-status {
display: block;
}
.device-entry-info-modal .device-details-info-header .device-name {
font-size: 2.4rem;
font-weight: 500;
}
.device-entry-info-modal .device-details-info-header .device-online-status {
font-style: italic;
}
.device-entry-info-modal .device-details-info-header .device-online-status::before {
content: "(";
}
.device-entry-info-modal .device-details-info-header .device-online-status::after {
content: ")";
}
.device-entry-info-modal .device-volume {
display: inline-block;
width: 100%;
-moz-column-break-inside: avoid;
break-inside: avoid;
}
.device-entry-info-modal .device-os-and-connection .fa-check {
color: #24E873;
}
.device-entry-info-modal .device-os-and-connection .fa-times {
color: #FF005A;
}
(function(){
var PropTypes, ref$, button, dd, div, dt, dl, i, li, span, ul, CSSTransitionGroup, availableVolumes, MorphButtonToModal, DeviceInfoButtonModal, slice$ = [].slice;
PropTypes = React.PropTypes;
ref$ = React.DOM, button = ref$.button, dd = ref$.dd, div = ref$.div, dt = ref$.dt, dl = ref$.dl, i = ref$.i, li = ref$.li, span = ref$.span, ul = ref$.ul;
CSSTransitionGroup = React.addons.CSSTransitionGroup;
availableVolumes = [
{
name: "iPhoto"
}, {
name: "LightRoom"
}, {
name: "Macintosh HD",
subdirs: ["Users/lucius"]
}, {
name: "Lucius's Biig Hard Drive Name"
}, {
name: "MOVIES"
}, {
name: "Music"
}, {
name: "OnePlus Two"
}, {
name: "NSFW",
subdirs: ["latina", "teen", "twins", "snakes"]
}, {
name: "Lucius Thumb"
}, {
name: "Snakes"
}, {
name: "Animu"
}
];
MorphButtonToModal = React.createClass({
name: "MorphButtonToModal",
propTypes: {
buttonDom: PropTypes.node,
titleDom: PropTypes.node
},
getInitialState: function getInitialState(){
return {
isOpen: false,
mainTranslateCoord: {
x: 0,
y: 0
}
};
},
componentWillUnmount: function componentWillUnmount(){
window.cancelAnimationFrame(this.mainTranslateAnim);
window.removeEventListener("resize", this.boundResizeHandler, false);
document.removeEventListener("click", this.clickOutClose, false);
},
mainTranslateDuration: 600,
coordToTranslate: function coordToTranslate(arg$){
var x, y;
x = arg$.x, y = arg$.y;
return "translate(" + x + "px, " + y + "px)";
},
quadInOut: function quadInOut(time, begin, end, duration){
if ((time = time / (duration / 2)) < 1) {
return (end - begin) / 2 * time * time + begin;
} else {
return (end - begin) * -1 / 2 * ((time -= 1) * (time - 2) - 1) + begin;
}
},
mainTranslateBack: function mainTranslateBack(){
var startTime, startX, startY, duration, translate, this$ = this;
startTime = window.performance.now();
startX = this.state.mainTranslateCoord.x;
startY = this.state.mainTranslateCoord.y;
duration = this.mainTranslateDuration;
translate = function(t){
var deltaTime, newCoord;
deltaTime = window.performance.now() - startTime;
newCoord = {
x: this$.quadInOut(deltaTime, startX, 0, duration),
y: this$.quadInOut(deltaTime, startY, 0, duration)
};
this$.setState({
mainTranslateCoord: newCoord
});
if (deltaTime < duration) {
return this$.mainTranslateAnim = window.requestAnimationFrame(translate);
}
};
translate();
},
mainTranslateToCenter: function mainTranslateToCenter(){
var morphMain, startTime, rect, startX, startY, duration, translate, this$ = this;
morphMain = this.refs.morphMain;
startTime = window.performance.now();
rect = morphMain.getBoundingClientRect();
startX = rect.left;
startY = rect.top;
duration = this.mainTranslateDuration;
translate = function(t){
var deltaTime, ref$, width, height, newCoord;
deltaTime = window.performance.now() - startTime;
ref$ = morphMain.getBoundingClientRect(), width = ref$.width, height = ref$.height;
newCoord = {
x: this$.quadInOut(deltaTime, 0, (window.innerWidth - width) * 0.5 - startX, duration),
y: this$.quadInOut(deltaTime, 0, (window.innerHeight - height) * 0.5 - startY, duration)
};
this$.setState({
mainTranslateCoord: newCoord
});
if (deltaTime < duration) {
return this$.mainTranslateAnim = window.requestAnimationFrame(translate);
}
};
translate();
},
resizeHandler: function resizeHandler(event){
var ref$, top, left, width, height, newCoord;
ref$ = this.refs.morphWrapper.getBoundingClientRect(), top = ref$.top, left = ref$.left;
ref$ = this.refs.morphMain.getBoundingClientRect(), width = ref$.width, height = ref$.height;
newCoord = {
x: (window.innerWidth - width) * 0.5 - left,
y: (window.innerHeight - height) * 0.5 - top
};
this.setState({
mainTranslateCoord: newCoord
});
},
toggleClickOutClose: function toggleClickOutClose(){
var this$ = this;
if (this.state.isOpen) {
this.boundResizeHandler = this.resizeHandler.bind(this);
this.clickOutClose = function(event){
if (!event.target.closest(".morph-modal-container")) {
return this$.closeModal();
}
};
window.addEventListener("resize", this.boundResizeHandler, false);
document.addEventListener("click", this.clickOutClose, false);
} else {
window.removeEventListener("resize", this.boundResizeHandler, false);
document.removeEventListener("click", this.clickOutClose, false);
}
},
openModal: function openModal(event){
this.mainTranslateToCenter();
this.setState({
isOpen: true
}, this.toggleClickOutClose);
},
closeModal: function closeModal(event){
this.mainTranslateBack();
this.setState({
isOpen: false
}, this.toggleClickOutClose);
},
renderButton: function renderButton(){
return div({
ref: "morphButtonContainer",
className: "morph-button-container"
}, button({
ref: "morphButton",
className: "morph-button",
onClick: this.openModal
}, this.props.buttonDom));
},
renderModal: function renderModal(){
return div({
ref: "morphModalContainer",
className: "morph-modal-container"
}, div({
ref: "morphModalTitle",
className: "morph-modal-title"
}, this.props.titleDom, button({
ref: "morphCloseButton",
className: "btn-close",
onClick: this.closeModal
}, i({
ref: "morphCloseButtonIcon",
className: "fa fa-times"
}), span({
ref: "morphCloseButtonLabel",
className: "sr-only"
}, "Close"))), div({
ref: "morphModalBody",
className: "morph-modal-body"
}, this.props.children));
},
render: function render(){
var classNames, wrapperClassNames;
classNames = ["morph-button-to-modal", this.state.isOpen ? "open" : "closed", this.props.className].join(" ").trim();
wrapperClassNames = classNames.split(" ").map(function(s){
return s + "-wrapper";
}).join(" ");
return div({
ref: "morphWrapper",
className: wrapperClassNames
}, div({
ref: "morphMain",
key: "morphButtonToModal",
className: classNames,
style: {
transform: this.coordToTranslate(this.state.mainTranslateCoord)
}
}, React.createElement(CSSTransitionGroup, {
key: "morphButtonTrans",
transitionName: "morph-button",
transitionEnterTimeout: 700,
transitionLeaveTimeout: 200
}, this.state.isOpen
? null
: this.renderButton()), React.createElement(CSSTransitionGroup, {
key: "morphModalTrans",
transitionName: "morph-modal",
transitionEnterTimeout: 1200,
transitionLeaveTimeout: 200
}, this.state.isOpen ? this.renderModal() : null)));
}
});
DeviceInfoButtonModal = React.createClass({
name: "DeviceInfoButtonModal",
propTypes: {
volumes: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string.isRequired,
subdirs: PropTypes.arrayOf(PropTypes.string)
}))
},
renderVolume: function renderVolume(colIdx, vol, idx){
idx == null && (idx = 0);
return div({
key: "vol" + colIdx + "." + idx,
className: "device-volume"
}, [dl({
key: colIdx + "." + idx,
className: "info-key-value"
}, dt({
key: "key",
className: "info-key"
}, vol.name), dd({
key: "value",
className: "info-value"
}, "Available"))].concat(!vol.subdirs || !vol.subdirs.length
? []
: vol.subdirs.map(function(sub, idx){
return dl({
key: idx,
className: "info-key-value"
}, [
dt({
key: "subkey" + idx,
className: "sub info-key"
}, sub), dd({
key: "subvalue" + idx,
className: "sub info-value"
}, "Available")
]);
})));
},
renderVolumes: function renderVolumes(volumes, count){
var splitAt, splitVolumes, this$ = this;
count = count || this['this'].props.volumes.reduce(function(acc, vol){
return acc + 1 + (vol.subdirs ? vol.subdirs.length : 0);
}, 0);
if (count < 7) {
return div({
key: "vol-list-0",
className: "device-volume-list",
style: {
flexBasis: "50%",
maxWidth: "50%",
paddingLeft: "9rem"
}
}, volumes.map(this.renderVolume.bind(this, 0)));
} else {
splitAt = Math.ceil(count * 0.5);
splitVolumes = function(arg$, count_, acc){
var head, tail;
head = arg$[0], tail = slice$.call(arg$, 1);
count_ == null && (count_ = 0);
acc == null && (acc = [[], []]);
acc[count_ < splitAt ? 0 : 1].push(head);
if (deepEq$(tail.length, 0, '===')) {
return acc;
} else {
return splitVolumes(tail, count_ + 1 + (head.subdirs ? head.subdirs.length : 0), acc);
}
};
return splitVolumes(volumes).map(function(volColumn, idx){
return div({
key: "vol-list-" + idx,
className: "device-volume-list"
}, volColumn.map(this$.renderVolume.bind(this$, idx)));
});
}
},
renderDeviceDetailsInfo: function renderDeviceDetailsInfo(){
var volCount;
volCount = this.props.volumes.reduce(function(acc, vol){
return acc + 1 + (vol.subdirs ? vol.subdirs.length : 0);
}, 0);
return div({
className: "device-details-info"
}, [div({
key: "os-conn-0",
className: "device-os-and-connection",
style: volCount < 7
? {
flexBasis: "50%",
maxWidth: "50%",
paddingRight: "9rem"
}
: {}
}, dl({
className: "info-key-value"
}, dt({
className: "info-key"
}, "Operating System"), dd({
className: "info-value"
}, "OS X")), dl({
className: "info-key-value"
}, dt({
className: "info-key"
}, i({
className: "fa fa-check"
}, null), span(null, " LAN")), dd({
className: "info-value"
}, "192.168.1.1:8111")), dl({
className: "info-key-value"
}, dt({
className: "info-key"
}, i({
className: "fa fa-times"
}, null), span(null, " P2P")), dd({
className: "info-value"
}, "none")), dl({
className: "info-key-value"
}, dt({
className: "info-key"
}, i({
className: "fa fa-check"
}, null), span(null, " Relay")), dd({
className: "info-value"
}, "toast.al")))].concat(this.renderVolumes(availableVolumes, volCount)));
},
renderButtonDom: [
i({
key: "buttonIcon",
className: "info-icon fa fa-info"
}, null), span({
key: "buttonLabel",
className: "info-label sr-only"
}, "Device Info")
],
renderTitleDom: [
i({
key: "titleIcon",
className: "title-icon fa fa-desktop",
style: {
paddingRight: "0.5em"
}
}, null), span({
key: "titleLabel",
className: "title-label"
}, "Devices Info")
],
render: function render(){
return React.createElement(MorphButtonToModal, {
key: "deviceEntryInfoModal",
className: "device-entry-info-modal",
buttonDom: this.renderButtonDom,
titleDom: this.renderTitleDom
}, div({
key: "deviceDetailsInfoContainer",
className: "device-details-info-container"
}, div({
className: "device-details-info-header"
}, i({
className: "device-image fa fa-desktop"
}, null), div({
className: "device-label"
}, span({
className: "device-name"
}, "Lucius Desktop"), span({
className: "device-online-status"
}, "Online"))), this.renderDeviceDetailsInfo()));
}
});
ReactDOM.render(React.createElement(DeviceInfoButtonModal, {
volumes: availableVolumes
}), document.getElementById("app"));
function deepEq$(x, y, type){
var toString = {}.toString, hasOwnProperty = {}.hasOwnProperty,
has = function (obj, key) { return hasOwnProperty.call(obj, key); };
var first = true;
return eq(x, y, []);
function eq(a, b, stack) {
var className, length, size, result, alength, blength, r, key, ref, sizeB;
if (a == null || b == null) { return a === b; }
if (a.__placeholder__ || b.__placeholder__) { return true; }
if (a === b) { return a !== 0 || 1 / a == 1 / b; }
className = toString.call(a);
if (toString.call(b) != className) { return false; }
switch (className) {
case '[object String]': return a == String(b);
case '[object Number]':
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
case '[object Date]':
case '[object Boolean]':
return +a == +b;
case '[object RegExp]':
return a.source == b.source &&
a.global == b.global &&
a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase;
}
if (typeof a != 'object' || typeof b != 'object') { return false; }
length = stack.length;
while (length--) { if (stack[length] == a) { return true; } }
stack.push(a);
size = 0;
result = true;
if (className == '[object Array]') {
alength = a.length;
blength = b.length;
if (first) {
switch (type) {
case '===': result = alength === blength; break;
case '<==': result = alength <= blength; break;
case '<<=': result = alength < blength; break;
}
size = alength;
first = false;
} else {
result = alength === blength;
size = alength;
}
if (result) {
while (size--) {
if (!(result = size in a == size in b && eq(a[size], b[size], stack))){ break; }
}
}
} else {
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) {
return false;
}
for (key in a) {
if (has(a, key)) {
size++;
if (!(result = has(b, key) && eq(a[key], b[key], stack))) { break; }
}
}
if (result) {
sizeB = 0;
for (key in b) {
if (has(b, key)) { ++sizeB; }
}
if (first) {
if (type === '<<=') {
result = size < sizeB;
} else if (type === '<==') {
result = size <= sizeB
} else {
result = size === sizeB;
}
} else {
first = false;
result = size === sizeB;
}
}
}
stack.pop();
return result;
}
}
}).call(this);
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css'>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-with-addons.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.js'></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- This script got from frontendfreecode.com -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css'>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-with-addons.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.js'></script>
<style>
@charset "UTF-8";
html {
box-sizing: border-box;
background-color: #2d3437;
font-size: 62.5%;
font-family: Roboto, Helvetica, sans-serif;
overflow: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
*, *::before, *::after {
box-sizing: inherit;
}
html, body {
height: 100%;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
#app {
display: flex;
flex: 1 1 auto;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.morph-button-to-modal-wrapper {
position: relative;
overflow: visible;
top: 80vh;
left: 10vw;
width: 3.2rem;
height: 3.2rem;
}
.morph-button-to-modal {
position: relative;
top: 0;
bottom: 0;
overflow: hidden;
min-width: 3.2rem;
min-height: 3.2rem;
width: 3.2rem;
max-height: 3.2rem;
border: 0.2rem solid #fff;
border-radius: 50%;
background: transparent;
color: #fff;
will-change: content, width, max-width, max-height, transform;
transition-property: width, max-width, max-height, border-color, border-radius, background-color;
transition-duration: 350ms, 350ms, 350ms, 200ms, 200ms, 400ms;
transition-timing-function: cubic-bezier(0.46, 0.03, 0.52, 0.96);
transition-delay: 100ms, 100ms, 200ms, 400ms, 400ms, 200ms;
}
.morph-button-to-modal.open {
z-index: 1000;
width: 90rem;
max-width: calc(100vw - 2rem);
max-height: calc(100vh - 2rem);
border-color: transparent;
border-radius: 1rem;
background-color: #394144;
transition-delay: 200ms, 200ms, 200ms, 200ms, 200ms, 200ms;
}
.morph-button-to-modal button {
appearence: none;
background: none;
border: none;
padding: 0;
}
.morph-button-to-modal .morph-button-enter {
opacity: 0.01;
}
.morph-button-to-modal .morph-button-enter.morph-button-enter-active {
opacity: 1;
transition-property: opacity;
transition-duration: 300ms;
transition-timing-function: ease-out;
transition-delay: 400ms;
}
.morph-button-to-modal .morph-button-leave {
opacity: 1;
}
.morph-button-to-modal .morph-button-leave.morph-button-leave-active {
opacity: 0;
transition: opacity 200ms ease-out;
}
.morph-button-to-modal .morph-modal-enter {
opacity: 0.01;
}
.morph-button-to-modal .morph-modal-enter.morph-modal-enter-active {
opacity: 1;
transition-property: opacity 320ms ease-out 500ms;
}
.morph-button-to-modal .morph-modal-leave {
opacity: 1;
}
.morph-button-to-modal .morph-modal-leave.morph-modal-leave-active {
opacity: 0;
transition: opacity 200ms ease-out;
}
.morph-button-to-modal .morph-button {
position: absolute;
width: 100%;
height: 100%;
}
.morph-button-to-modal .morph-modal-container {
display: flex;
flex-flow: column nowrap;
align-items: stretch;
position: relative;
padding: 2rem;
}
.morph-button-to-modal .morph-modal-title {
flex: 0 0 auto;
overflow: hidden;
padding-bottom: 2rem;
border-bottom: 0.1rem solid #545e61;
font-size: 2rem;
font-weight: 500;
white-space: nowrap;
text-overflow: ellipsis;
}
.morph-button-to-modal .btn-close {
position: absolute;
top: 1.4rem;
right: 2rem;
color: #b0b5b8;
font-size: 2.4rem;
}
.morph-button-to-modal .morph-modal-body {
flex: 0 1 auto;
overflow-y: auto;
max-height: calc(100vh - 14rem);
font-size: 1.5rem;
}
.device-entry-info-modal .morph-modal-enter .device-details-info > * {
border-color: transparent;
}
.device-entry-info-modal .morph-modal-enter .device-details-info > * > * {
opacity: 0.01;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * {
border-left-color: #545e61;
transition: border-color 250ms ease-in 500ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > * {
opacity: 1;
transition: opacity 300ms ease-in 420ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(1) {
transition-delay: 452ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(2) {
transition-delay: 484ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(3) {
transition-delay: 516ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(4) {
transition-delay: 548ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(5) {
transition-delay: 580ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(6) {
transition-delay: 612ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(7) {
transition-delay: 644ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(8) {
transition-delay: 676ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(9) {
transition-delay: 708ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(10) {
transition-delay: 740ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(11) {
transition-delay: 772ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(12) {
transition-delay: 804ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(13) {
transition-delay: 836ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(14) {
transition-delay: 868ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(15) {
transition-delay: 900ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(16) {
transition-delay: 932ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(17) {
transition-delay: 964ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(18) {
transition-delay: 996ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(19) {
transition-delay: 1028ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(20) {
transition-delay: 1060ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(21) {
transition-delay: 1092ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(22) {
transition-delay: 1124ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(23) {
transition-delay: 1156ms;
}
.device-entry-info-modal .morph-modal-enter.morph-modal-enter-active .device-details-info > * > *:nth-child(24) {
transition-delay: 1188ms;
}
.device-entry-info-modal .modal-button {
font-size: 3.2rem;
}
.device-entry-info-modal .info-key-value {
display: flex;
justify-content: space-between;
white-space: nowrap;
line-height: 2.5;
}
.device-entry-info-modal .info-key-value, .device-entry-info-modal .info-key-value .info-key, .device-entry-info-modal .info-key-value .info-value {
margin: 0;
}
.device-entry-info-modal .info-key-value .info-key {
flex: 0 1 auto;
overflow: hidden;
padding-right: 1em;
color: #fff;
font-weight: 600;
text-overflow: ellipsis;
}
.device-entry-info-modal .info-key-value .info-value {
flex: 0 0 auto;
text-align: right;
color: #b0b5b8;
}
.device-entry-info-modal .device-details-info {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
width: 100%;
max-width: 100%;
margin: 3rem 0;
}
.device-entry-info-modal .device-details-info > * {
flex: 0 1 33.33333%;
max-width: 33.33333%;
padding: 0 3rem;
border-left: 0.1rem solid #545e61;
}
.device-entry-info-modal .device-details-info > *:first-of-type {
border: none;
padding-left: 0;
}
.device-entry-info-modal .device-details-info > *:last-of-type {
padding-right: 0;
}
.device-entry-info-modal .sub.info-key::before {
content: "↳";
margin-right: 0.5em;
font-family: sans-serif;
color: #b0b5b8;
}
.device-entry-info-modal .device-details-info-header {
display: flex;
flex-flow: row nowrap;
align-content: center;
margin-bottom: 4rem;
padding: 2.4rem 0 1.8rem;
border-bottom: 0.1rem solid #545e61;
}
.device-entry-info-modal .device-details-info-header .device-image {
margin-right: 2.8rem;
color: #36d3b4;
font-size: 6.4rem;
}
.device-entry-info-modal .device-details-info-header .device-name, .device-entry-info-modal .device-details-info-header .device-online-status {
display: block;
}
.device-entry-info-modal .device-details-info-header .device-name {
font-size: 2.4rem;
font-weight: 500;
}
.device-entry-info-modal .device-details-info-header .device-online-status {
font-style: italic;
}
.device-entry-info-modal .device-details-info-header .device-online-status::before {
content: "(";
}
.device-entry-info-modal .device-details-info-header .device-online-status::after {
content: ")";
}
.device-entry-info-modal .device-volume {
display: inline-block;
width: 100%;
-moz-column-break-inside: avoid;
break-inside: avoid;
}
.device-entry-info-modal .device-os-and-connection .fa-check {
color: #24E873;
}
.device-entry-info-modal .device-os-and-connection .fa-times {
color: #FF005A;
}
</style>
</head>
<body>
<div id="app"></div><div id="bcl"><a style="font-size:8pt;text-decoration:none;" href="http://www.devanswer.com">Free Frontend</a></div>
<script>
(function(){
var PropTypes, ref$, button, dd, div, dt, dl, i, li, span, ul, CSSTransitionGroup, availableVolumes, MorphButtonToModal, DeviceInfoButtonModal, slice$ = [].slice;
PropTypes = React.PropTypes;
ref$ = React.DOM, button = ref$.button, dd = ref$.dd, div = ref$.div, dt = ref$.dt, dl = ref$.dl, i = ref$.i, li = ref$.li, span = ref$.span, ul = ref$.ul;
CSSTransitionGroup = React.addons.CSSTransitionGroup;
availableVolumes = [
{
name: "iPhoto"
}, {
name: "LightRoom"
}, {
name: "Macintosh HD",
subdirs: ["Users/lucius"]
}, {
name: "Lucius's Biig Hard Drive Name"
}, {
name: "MOVIES"
}, {
name: "Music"
}, {
name: "OnePlus Two"
}, {
name: "NSFW",
subdirs: ["latina", "teen", "twins", "snakes"]
}, {
name: "Lucius Thumb"
}, {
name: "Snakes"
}, {
name: "Animu"
}
];
MorphButtonToModal = React.createClass({
name: "MorphButtonToModal",
propTypes: {
buttonDom: PropTypes.node,
titleDom: PropTypes.node
},
getInitialState: function getInitialState(){
return {
isOpen: false,
mainTranslateCoord: {
x: 0,
y: 0
}
};
},
componentWillUnmount: function componentWillUnmount(){
window.cancelAnimationFrame(this.mainTranslateAnim);
window.removeEventListener("resize", this.boundResizeHandler, false);
document.removeEventListener("click", this.clickOutClose, false);
},
mainTranslateDuration: 600,
coordToTranslate: function coordToTranslate(arg$){
var x, y;
x = arg$.x, y = arg$.y;
return "translate(" + x + "px, " + y + "px)";
},
quadInOut: function quadInOut(time, begin, end, duration){
if ((time = time / (duration / 2)) < 1) {
return (end - begin) / 2 * time * time + begin;
} else {
return (end - begin) * -1 / 2 * ((time -= 1) * (time - 2) - 1) + begin;
}
},
mainTranslateBack: function mainTranslateBack(){
var startTime, startX, startY, duration, translate, this$ = this;
startTime = window.performance.now();
startX = this.state.mainTranslateCoord.x;
startY = this.state.mainTranslateCoord.y;
duration = this.mainTranslateDuration;
translate = function(t){
var deltaTime, newCoord;
deltaTime = window.performance.now() - startTime;
newCoord = {
x: this$.quadInOut(deltaTime, startX, 0, duration),
y: this$.quadInOut(deltaTime, startY, 0, duration)
};
this$.setState({
mainTranslateCoord: newCoord
});
if (deltaTime < duration) {
return this$.mainTranslateAnim = window.requestAnimationFrame(translate);
}
};
translate();
},
mainTranslateToCenter: function mainTranslateToCenter(){
var morphMain, startTime, rect, startX, startY, duration, translate, this$ = this;
morphMain = this.refs.morphMain;
startTime = window.performance.now();
rect = morphMain.getBoundingClientRect();
startX = rect.left;
startY = rect.top;
duration = this.mainTranslateDuration;
translate = function(t){
var deltaTime, ref$, width, height, newCoord;
deltaTime = window.performance.now() - startTime;
ref$ = morphMain.getBoundingClientRect(), width = ref$.width, height = ref$.height;
newCoord = {
x: this$.quadInOut(deltaTime, 0, (window.innerWidth - width) * 0.5 - startX, duration),
y: this$.quadInOut(deltaTime, 0, (window.innerHeight - height) * 0.5 - startY, duration)
};
this$.setState({
mainTranslateCoord: newCoord
});
if (deltaTime < duration) {
return this$.mainTranslateAnim = window.requestAnimationFrame(translate);
}
};
translate();
},
resizeHandler: function resizeHandler(event){
var ref$, top, left, width, height, newCoord;
ref$ = this.refs.morphWrapper.getBoundingClientRect(), top = ref$.top, left = ref$.left;
ref$ = this.refs.morphMain.getBoundingClientRect(), width = ref$.width, height = ref$.height;
newCoord = {
x: (window.innerWidth - width) * 0.5 - left,
y: (window.innerHeight - height) * 0.5 - top
};
this.setState({
mainTranslateCoord: newCoord
});
},
toggleClickOutClose: function toggleClickOutClose(){
var this$ = this;
if (this.state.isOpen) {
this.boundResizeHandler = this.resizeHandler.bind(this);
this.clickOutClose = function(event){
if (!event.target.closest(".morph-modal-container")) {
return this$.closeModal();
}
};
window.addEventListener("resize", this.boundResizeHandler, false);
document.addEventListener("click", this.clickOutClose, false);
} else {
window.removeEventListener("resize", this.boundResizeHandler, false);
document.removeEventListener("click", this.clickOutClose, false);
}
},
openModal: function openModal(event){
this.mainTranslateToCenter();
this.setState({
isOpen: true
}, this.toggleClickOutClose);
},
closeModal: function closeModal(event){
this.mainTranslateBack();
this.setState({
isOpen: false
}, this.toggleClickOutClose);
},
renderButton: function renderButton(){
return div({
ref: "morphButtonContainer",
className: "morph-button-container"
}, button({
ref: "morphButton",
className: "morph-button",
onClick: this.openModal
}, this.props.buttonDom));
},
renderModal: function renderModal(){
return div({
ref: "morphModalContainer",
className: "morph-modal-container"
}, div({
ref: "morphModalTitle",
className: "morph-modal-title"
}, this.props.titleDom, button({
ref: "morphCloseButton",
className: "btn-close",
onClick: this.closeModal
}, i({
ref: "morphCloseButtonIcon",
className: "fa fa-times"
}), span({
ref: "morphCloseButtonLabel",
className: "sr-only"
}, "Close"))), div({
ref: "morphModalBody",
className: "morph-modal-body"
}, this.props.children));
},
render: function render(){
var classNames, wrapperClassNames;
classNames = ["morph-button-to-modal", this.state.isOpen ? "open" : "closed", this.props.className].join(" ").trim();
wrapperClassNames = classNames.split(" ").map(function(s){
return s + "-wrapper";
}).join(" ");
return div({
ref: "morphWrapper",
className: wrapperClassNames
}, div({
ref: "morphMain",
key: "morphButtonToModal",
className: classNames,
style: {
transform: this.coordToTranslate(this.state.mainTranslateCoord)
}
}, React.createElement(CSSTransitionGroup, {
key: "morphButtonTrans",
transitionName: "morph-button",
transitionEnterTimeout: 700,
transitionLeaveTimeout: 200
}, this.state.isOpen
? null
: this.renderButton()), React.createElement(CSSTransitionGroup, {
key: "morphModalTrans",
transitionName: "morph-modal",
transitionEnterTimeout: 1200,
transitionLeaveTimeout: 200
}, this.state.isOpen ? this.renderModal() : null)));
}
});
DeviceInfoButtonModal = React.createClass({
name: "DeviceInfoButtonModal",
propTypes: {
volumes: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string.isRequired,
subdirs: PropTypes.arrayOf(PropTypes.string)
}))
},
renderVolume: function renderVolume(colIdx, vol, idx){
idx == null && (idx = 0);
return div({
key: "vol" + colIdx + "." + idx,
className: "device-volume"
}, [dl({
key: colIdx + "." + idx,
className: "info-key-value"
}, dt({
key: "key",
className: "info-key"
}, vol.name), dd({
key: "value",
className: "info-value"
}, "Available"))].concat(!vol.subdirs || !vol.subdirs.length
? []
: vol.subdirs.map(function(sub, idx){
return dl({
key: idx,
className: "info-key-value"
}, [
dt({
key: "subkey" + idx,
className: "sub info-key"
}, sub), dd({
key: "subvalue" + idx,
className: "sub info-value"
}, "Available")
]);
})));
},
renderVolumes: function renderVolumes(volumes, count){
var splitAt, splitVolumes, this$ = this;
count = count || this['this'].props.volumes.reduce(function(acc, vol){
return acc + 1 + (vol.subdirs ? vol.subdirs.length : 0);
}, 0);
if (count < 7) {
return div({
key: "vol-list-0",
className: "device-volume-list",
style: {
flexBasis: "50%",
maxWidth: "50%",
paddingLeft: "9rem"
}
}, volumes.map(this.renderVolume.bind(this, 0)));
} else {
splitAt = Math.ceil(count * 0.5);
splitVolumes = function(arg$, count_, acc){
var head, tail;
head = arg$[0], tail = slice$.call(arg$, 1);
count_ == null && (count_ = 0);
acc == null && (acc = [[], []]);
acc[count_ < splitAt ? 0 : 1].push(head);
if (deepEq$(tail.length, 0, '===')) {
return acc;
} else {
return splitVolumes(tail, count_ + 1 + (head.subdirs ? head.subdirs.length : 0), acc);
}
};
return splitVolumes(volumes).map(function(volColumn, idx){
return div({
key: "vol-list-" + idx,
className: "device-volume-list"
}, volColumn.map(this$.renderVolume.bind(this$, idx)));
});
}
},
renderDeviceDetailsInfo: function renderDeviceDetailsInfo(){
var volCount;
volCount = this.props.volumes.reduce(function(acc, vol){
return acc + 1 + (vol.subdirs ? vol.subdirs.length : 0);
}, 0);
return div({
className: "device-details-info"
}, [div({
key: "os-conn-0",
className: "device-os-and-connection",
style: volCount < 7
? {
flexBasis: "50%",
maxWidth: "50%",
paddingRight: "9rem"
}
: {}
}, dl({
className: "info-key-value"
}, dt({
className: "info-key"
}, "Operating System"), dd({
className: "info-value"
}, "OS X")), dl({
className: "info-key-value"
}, dt({
className: "info-key"
}, i({
className: "fa fa-check"
}, null), span(null, " LAN")), dd({
className: "info-value"
}, "192.168.1.1:8111")), dl({
className: "info-key-value"
}, dt({
className: "info-key"
}, i({
className: "fa fa-times"
}, null), span(null, " P2P")), dd({
className: "info-value"
}, "none")), dl({
className: "info-key-value"
}, dt({
className: "info-key"
}, i({
className: "fa fa-check"
}, null), span(null, " Relay")), dd({
className: "info-value"
}, "toast.al")))].concat(this.renderVolumes(availableVolumes, volCount)));
},
renderButtonDom: [
i({
key: "buttonIcon",
className: "info-icon fa fa-info"
}, null), span({
key: "buttonLabel",
className: "info-label sr-only"
}, "Device Info")
],
renderTitleDom: [
i({
key: "titleIcon",
className: "title-icon fa fa-desktop",
style: {
paddingRight: "0.5em"
}
}, null), span({
key: "titleLabel",
className: "title-label"
}, "Devices Info")
],
render: function render(){
return React.createElement(MorphButtonToModal, {
key: "deviceEntryInfoModal",
className: "device-entry-info-modal",
buttonDom: this.renderButtonDom,
titleDom: this.renderTitleDom
}, div({
key: "deviceDetailsInfoContainer",
className: "device-details-info-container"
}, div({
className: "device-details-info-header"
}, i({
className: "device-image fa fa-desktop"
}, null), div({
className: "device-label"
}, span({
className: "device-name"
}, "Lucius Desktop"), span({
className: "device-online-status"
}, "Online"))), this.renderDeviceDetailsInfo()));
}
});
ReactDOM.render(React.createElement(DeviceInfoButtonModal, {
volumes: availableVolumes
}), document.getElementById("app"));
function deepEq$(x, y, type){
var toString = {}.toString, hasOwnProperty = {}.hasOwnProperty,
has = function (obj, key) { return hasOwnProperty.call(obj, key); };
var first = true;
return eq(x, y, []);
function eq(a, b, stack) {
var className, length, size, result, alength, blength, r, key, ref, sizeB;
if (a == null || b == null) { return a === b; }
if (a.__placeholder__ || b.__placeholder__) { return true; }
if (a === b) { return a !== 0 || 1 / a == 1 / b; }
className = toString.call(a);
if (toString.call(b) != className) { return false; }
switch (className) {
case '[object String]': return a == String(b);
case '[object Number]':
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
case '[object Date]':
case '[object Boolean]':
return +a == +b;
case '[object RegExp]':
return a.source == b.source &&
a.global == b.global &&
a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase;
}
if (typeof a != 'object' || typeof b != 'object') { return false; }
length = stack.length;
while (length--) { if (stack[length] == a) { return true; } }
stack.push(a);
size = 0;
result = true;
if (className == '[object Array]') {
alength = a.length;
blength = b.length;
if (first) {
switch (type) {
case '===': result = alength === blength; break;
case '<==': result = alength <= blength; break;
case '<<=': result = alength < blength; break;
}
size = alength;
first = false;
} else {
result = alength === blength;
size = alength;
}
if (result) {
while (size--) {
if (!(result = size in a == size in b && eq(a[size], b[size], stack))){ break; }
}
}
} else {
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) {
return false;
}
for (key in a) {
if (has(a, key)) {
size++;
if (!(result = has(b, key) && eq(a[key], b[key], stack))) { break; }
}
}
if (result) {
sizeB = 0;
for (key in b) {
if (has(b, key)) { ++sizeB; }
}
if (first) {
if (type === '<<=') {
result = size < sizeB;
} else if (type === '<==') {
result = size <= sizeB
} else {
result = size === sizeB;
}
} else {
first = false;
result = size === sizeB;
}
}
}
stack.pop();
return result;
}
}
}).call(this);
</script>
</body>
</html>