Socket
Socket
Sign inDemoInstall

curvy-tabs

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

curvy-tabs - npm Package Compare versions

Comparing version 1.0.0 to 2.0.0

203

index.js

@@ -7,17 +7,20 @@ /* eslint-env browser */

var stylesheet =
'.curvy-tabs-container {' +
'position: absolute;' +
'z-index: 0;' +
'.curvy-tabs-container {' +
'position: relative;' +
// 'z-index: 0;' +
'width: 500px;' +
'height: 500px;' +
'}\n' +
'.curvy-tabs-container > div {' +
'position: absolute;' +
'left: 0;' +
'bottom: 0;' +
'right: 0;' +
'border: 1px solid #aaa;' +
'border-radius: 7px;' +
'}\n' +
'.curvy-tabs-bar {' +
'position: relative;' +
'z-index: 1;' +
'}\n' +
'.curvy-tabs-content {' +
'.curvy-tabs-container > div > * {' +
'position: absolute;' +
'display: block;' +
'visibility: hidden;' +
'position: absolute;' +
'padding: 8px;' +

@@ -28,3 +31,7 @@ 'top: 0;' +

'right: 0;' +
'overflow: scroll;border-radius:7px' +
'overflow: scroll;' +
'border-radius: 7px;' +
'}\n' +
'.curvy-tabs-container > canvas {' +
'position: absolute;' +
'}\n';

@@ -34,10 +41,9 @@

var TRANSPARENT = 'rgba(0, 0, 0, 0)';
function CurvyTabs(container, selectedContentElement) {
if (!document.head.querySelector('style#injected-stylesheet-curvy-tabs')) {
var el = document.createElement('style');
el.id = 'injected-stylesheet-curvy-tabs';
el.innerHTML = stylesheet;
document.head.insertBefore(el, document.head.firstElementChild);
}
injectStylesheet();
var children = Array.prototype.slice.call(container.children);
this.container = container;

@@ -47,6 +53,12 @@ this._minWidth = 0;

this._font = '10pt sans-serif';
this._selected = selectedContentElement || container.querySelector('.curvy-tabs-content');
this._selected = selectedContentElement || children[0];
var contents = this.contents = document.createElement('div');
children.forEach(function(child) {
contents.appendChild(child);
});
container.appendChild(contents);
var tabs = this.tabs = new WeakMap;
getContentsArray.call(this).forEach(function(content) {
this.contentDivs.forEach(function(content) {
tabs.set(content, {});

@@ -57,10 +69,8 @@ });

var containerRect = container.getBoundingClientRect();
var canvas = this.canvas = document.createElement('canvas');
var containerRect = container.getBoundingClientRect();
document.body.insertBefore(canvas, container);
canvas.style.left = containerRect.left - canvas.getBoundingClientRect().left + 'px';
canvas.classList.add('curvy-tabs-bar');
container.appendChild(canvas);
canvas.width = containerRect.width;
this.containerHeight = this.containerHeight; // sets canvas bottom margin
this.height = CurvyTabs.height; // invokes paint()
this.size = CurvyTabs.size;
this.height = this.height; // invoke setter to calculate and set content height; invokes paint()

@@ -70,3 +80,3 @@ this.canvas.addEventListener('click', clickHandler.bind(this));

CurvyTabs.height = 29;
CurvyTabs.size = 29;

@@ -76,20 +86,21 @@ CurvyTabs.prototype = {

destruct: function() {
this.canvas.remove();
this.container.style.position = 'static';
},
addTab: function(name, html, color) {
var content = document.createElement('div');
content.name = name;
content.className = 'curvy-tabs-content';
content.setAttribute('name', name);
if (html) {
content.innerHTML = html;
}
if (color) {
content.style.backgroundColor = color;
}
content.innerHTML = html;
this.tabs.set(content, {});
this.container.appendChild(content);
this.contents.appendChild(content);
this.selected = content;
this.paint();
},
get contentDivs() {
return Array.prototype.slice.call(this.contents.children);
},
get minWidth() {

@@ -112,18 +123,17 @@ return this._minWidth;

get height() {
return this.height;
get size() {
return this.canvas.height;
},
set height(height) {
this.canvas.height = height;
this.container.style.top = window.scrollY + this.canvas.getBoundingClientRect().bottom - 1 + 'px';
set size(size) {
this.canvas.height = size;
this.contents.style.top = size - 1 + 'px';
this.paint();
},
get containerHeight() {
get height() {
return this.container.getBoundingClientRect().height;
},
set containerHeight(height) {
var style = window.getComputedStyle(this.container);
set height(height) {
this.container.style.height = height + 'px';
this.canvas.style.marginBottom = parseInt(style.height) + parseInt(style.marginBottom) + 'px';
this.contents.style.top = this.size - borderWidth.call(this) + 'px';
this.paint();

@@ -138,3 +148,3 @@ },

this.paint();
this.container.style.borderRadius = curviness * 7 + 'px';
this.contents.style.borderRadius = curviness * 7 + 'px';
setContentsBorderRadius.call(this);

@@ -151,10 +161,2 @@ },

get borderColor() {
return window.getComputedStyle(this.container).borderTopColor;
},
set borderColor(color) {
tabBar.container.style.borderColor = color;
tabBar.paint();
},
get selected() {

@@ -168,2 +170,13 @@ return this._selected;

css: function(keyOrObject, value) {
css.call(this, this.contents, keyOrObject, value);
this.height = this.height; // invoke setter to reset overlap per possible border width change; invokes paint()
},
contentCss: function(keyOrObject, value) {
this.contentDivs.forEach(function(content) {
css.call(this, content, keyOrObject, value);
});
},
paint: function() {

@@ -174,6 +187,6 @@ var x = 8;

this.gc.textAlign = 'center';
this.gc.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.gc.clearRect(0, 0, this.canvas.width, this.size);
this.gc.font = this.font;
var contents = getContentsArray.call(this);
var contents = this.contentDivs;
if (contents.length) {

@@ -183,3 +196,3 @@ contents.forEach(function(content) {

x += props.width = drawTab.call(this, content, props.left = x);
x -= (0.80 - this.curviness * 0.11) * this.canvas.height; // overlap tabs
x -= (0.80 - this.curviness * 0.11) * this.size; // overlap tabs
}, this);

@@ -192,9 +205,34 @@ drawTab.call(this, this.selected, this.tabs.get(this.selected).left, true);

function getContentsArray() {
return Array.prototype.slice.call(this.container.querySelectorAll('.curvy-tabs-content'));
function css(el, keyOrObject, value) {
var style = el.style;
if (typeof keyOrObject === 'object' && !Array.isArray(keyOrObject)) {
Object.keys(keyOrObject).forEach(function(key) {
style[key] = keyOrObject[key];
})
} else if (arguments.length === 3) {
style[keyOrObject] = value;
} else if (arguments.length === 2) {
if (Array.isArray(keyOrObject)) {
return keyOrObject.reduce(function(dict, key) {
dict[key] = style[key];
return dict;
}, {});
} else {
return window.getComputedStyle(el)[keyOrObject];
}
}
}
function injectStylesheet() {
if (!document.head.querySelector('style#injected-stylesheet-curvy-tabs')) {
var el = document.createElement('style');
el.id = 'injected-stylesheet-curvy-tabs';
el.innerHTML = stylesheet;
document.head.insertBefore(el, document.head.firstElementChild);
}
}
function setContentsBorderRadius() {
var borderRadius = this.container.style.borderRadius;
getContentsArray.call(this).forEach(function(content) {
var borderRadius = this.contents.style.borderRadius;
this.contentDivs.forEach(function(content) {
content.style.borderRadius = borderRadius;

@@ -204,11 +242,28 @@ });

function contentStyle() {
return window.getComputedStyle(this.contents);
}
function borderWidth() {
return parseFloat(contentStyle.call(this).borderWidth);
}
function drawTab(content, x, onTop) {
var gc = this.gc;
var height = this.canvas.height - 1;
var curveWidth = .5 * height;
var size = this.size - 1;
var curveWidth = .5 * size;
var cw80 = this.curviness * 0.80 * curveWidth;
var text = content.getAttribute('name');
var w = Math.max(this.minWidth, PADDING + gc.measureText(text).width + PADDING);
var color = window.getComputedStyle(content).backgroundColor;
for (var el = content, color = TRANSPARENT; color === TRANSPARENT; el = el.parentElement) {
color = window.getComputedStyle(el).backgroundColor;
if (el === document.body) {
if (color === TRANSPARENT) {
color = 'white';
}
break;
}
}
gc.save(); // Save current transformation

@@ -218,6 +273,8 @@

gc.lineWidth = borderWidth.call(this);
if (onTop) {
gc.beginPath();
gc.moveTo(GAP, height); // Begin a new subpath there
gc.lineTo(GAP + curveWidth + w + curveWidth, height);
gc.moveTo(GAP, size); // Begin a new subpath there
gc.lineTo(GAP + curveWidth + w + curveWidth, size);
gc.strokeStyle = color;

@@ -228,10 +285,10 @@ gc.stroke();

gc.beginPath();
gc.moveTo(0, height); // Begin a new subpath there
gc.lineTo(GAP, height);
gc.moveTo(0, size); // Begin a new subpath there
gc.lineTo(GAP, size);
gc.translate(GAP, 0);
gc.bezierCurveTo(cw80, height, curveWidth - cw80, 0, curveWidth, 0);
gc.bezierCurveTo(cw80, size, curveWidth - cw80, 0, curveWidth, 0);
gc.lineTo(curveWidth + w, 0);
gc.translate(curveWidth + w, 0);
gc.bezierCurveTo(cw80, 0, curveWidth - cw80, height, curveWidth, height);
gc.lineTo(curveWidth + GAP, height);
gc.bezierCurveTo(cw80, 0, curveWidth - cw80, size, curveWidth, size);
gc.lineTo(curveWidth + GAP, size);

@@ -245,5 +302,5 @@ if (!onTop) {

gc.fillStyle = 'black';
gc.fillText(text, -w / 2, 2 * height / 3);
gc.fillText(text, -w / 2, 2 * size / 3);
gc.strokeStyle = this.borderColor;
gc.strokeStyle = contentStyle.call(this).borderColor;
gc.stroke();

@@ -265,5 +322,5 @@

function clickHandler(event) {
getContentsArray.call(this).find(function(content) {
this.contentDivs.find(function(content) {
var props = this.tabs.get(content);
var margin = GAP + .25 * this.canvas.height;
var margin = GAP + .25 * this.size;
var left = props.left + margin;

@@ -270,0 +327,0 @@ if (event.offsetX > left && event.offsetX < left + props.width - margin - margin) {

{
"name": "curvy-tabs",
"version": "1.0.0",
"version": "2.0.0",
"description": "Tab bar with fancy tabs",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -6,6 +6,6 @@ See the [demo](https://joneit.github.io/curvy-tabs/1.0.0).

<div class="curvy-tabs-container">
<div class="curvy-tabs-content" style="background-color:lightblue" name="Tab A">
<div style="background-color:lightblue" name="Tab A">
Content for Tab A goes here.
</div>
<div class="curvy-tabs-content" style="background-color:lightgreen" name="Tab B">
<div style="background-color:lightgreen" name="Tab B">
Content for Tab B goes here.

@@ -23,3 +23,3 @@ </div>

```
The following instantiates the controller object and adds the tab bar (a `canvas` element) above the container element:
The following instantiates the controller object, collecting all the content divs into a sub-div, and adds the tab bar (a `canvas` element) above it:
```js

@@ -32,6 +32,6 @@ var container = document.querySelector('.curvy-tabs-container'); // or whatever

### API
The first tab is selected by default. To programmatically specify some other tab, set `selected` to the content element:
The first tab is selected by default. To programmatically specify some other tab, set `selected` to a specific content div, either of the following works:
```js
var tabB = document.getElementByClassName('curvy-tabs-content')[1];
tabBar.selected = tabB; // or whatever
tabBar.selected = tabBar.contents.children[1];
tabBar.selected = tabBar.contents.querySelector('[name="Tab B"]');
```

@@ -58,13 +58,13 @@ To select an alternative tab on instantiation:

_Before instantiation,_ reset the default height (29 pixels):
_Before instantiation,_ reset the default tab size (initially 29 pixels):
```js
CurvyTabs.height = 40;
CurvyTabs.size = 40;
```
_After instantiation:_
```js
tabBar.height = 40;
tabBar.size = 40;
```
The container _must_ have a width and height. The default is 500 &times; 500 pixels.
_Before instantiation,_ use CSS (affects all instances):
_Before instantiation,_ use CSS to change the default (affects all instances):
```html

@@ -75,8 +75,8 @@ <style>

```
_After instantiation,_ container's width can be set programmatically:
_After instantiation,_ an instance's container width and height can be set programmatically:
```js
tabBar.width = 750; // sets both the tab bar width and the container width
tabBar.containerHeight = 1050;
tabBar.height = 1050;
```
To change the default border color (`#aaaaaa`):
Background color, border color, and border width affect both the tab bar and content area and can be set as follows:

@@ -86,16 +86,29 @@ _Before instantiation,_ use CSS (affects all instances):

<style>
.curvy-tabs-container { border-color: blue; }
.curvy-tabs-container > div {
border: 2x solid red;
background-color: yellow;
}
</style>
```
_After instantiation,_ can be set programmatically:
_After instantiation,_ such styles can be set programmatically using the `css` method (works like [jQuery's `css` method](http://api.jquery.com/css/)):
```js
tabBar.container.style.borderColor = 'blue';
tabBar.paint();
tabBar.css('borderColor', 'red'); // sets border color
tabBar.css('borderColor'); // returns border color
tabBar.css({ borderColor: 'yellow', backgroundColor: 'red' }); // sets both style properties
tabBar.css(['borderColor', 'backgroundColor']); // returns style dictionary
```
To change the default padding (`8px`), use CSS (affects all instances):
(Note that the content area background color serves as a default for transparent tabs; there is no point in setting this if all your tabs colors.)
To set styles on all the content divs at once:
_Before instantiation,_ use CSS (affects all instances):
```html
<style>
.curvy-tabs-content { padding: 3px }
.curvy-tabs-content > div > * { padding: 3px }
</style>
```
_After instantiation,_ use the `contentCss` method (also like jQuery's `css` method):
```js
tabBar.contentCss('padding', '2px');
```
### Event Handlers

@@ -122,2 +135,10 @@ #### `tabBar.onclick`

##### `event.stopPropagation()`
The event will be propagated to the `tabBar.onclick` handler (if defined) unless you call `event.stopPropagation()` from within.
The event will be propagated to the `tabBar.onclick` handler (if defined) unless you call `event.stopPropagation()` from within.
## Version History
* `1.0.0` — Initial version
* `2.0.0`
* Cleaner DOM structure
* `height` is now `size`
* `containerHeight` is now `height`
* added `contents`, `contentDivs`, css`, and `contentCss`
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc