Skip to content

Commit 51b9d52

Browse files
committed
moving to a custom element
1 parent e131443 commit 51b9d52

12 files changed

+378
-171
lines changed

.jshintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"describe": true,
2525
"it": true,
2626
"beforeEach": true,
27-
"afterEach": true
27+
"afterEach": true,
28+
"customElements": true
2829
}
2930
}

attribute-connect.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var canString = require("can-string");
2+
3+
module.exports = function(convertToProperty){
4+
convertToProperty = convertToProperty || canString.camelize;
5+
6+
return {
7+
attributeChangedCallback: function(name, oldValue, newValue){
8+
this[convertToProperty(name)] = newValue;
9+
},
10+
initialize: function(node){
11+
[].slice.call(node.attributes, 0).forEach(function(attrNode){
12+
node[convertToProperty(attrNode.name)] = attrNode.value;
13+
});
14+
}
15+
};
16+
};

demo.html

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<html>
2+
<bit-toc></bit-toc>
3+
<script>
4+
console.log("executing");
5+
6+
7+
console.log("executed");
8+
9+
function safeCustomElement(tag, constructor, prototype){
10+
var Element = function(){
11+
var result;
12+
if(typeof Reflect !== "undefined") {
13+
result = Reflect.construct(HTMLElement, [], new.target);
14+
} else {
15+
result = HTMLElement.apply(this, arguments);
16+
}
17+
18+
return result;
19+
}
20+
if(typeof HTMLElement !== undefined) {
21+
Element.prototype = Object.create(HTMLElement.prototype);
22+
}
23+
Object.getOwnPropertyNames(prototype).forEach(function(property){
24+
Object.defineProperty(Element.prototype, property,
25+
Object.getOwnPropertyDescriptor(prototype, property))
26+
});
27+
if(typeof customElements !== "undefined") {
28+
customElements.define(tag, Element);
29+
}
30+
31+
return Element;
32+
}
33+
34+
var BitToc = safeCustomElement('bit-toc',function(){
35+
console.log("constructor");
36+
},{
37+
connectedCallback: function(){
38+
console.log("connected");
39+
}
40+
});
41+
</script>
42+
</html>

make-tree.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ function makeTreeData(elements) {
6363

6464
return map.call(elements, function(element) {
6565
var text = element.textContent;
66-
var id = makeHeadingId(text);
66+
var id = element.id || makeHeadingId(text);
67+
element.id = id;
6768
var level = getElementLevel(element);
6869

6970
// generate unique id for elements with same text

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
"homepage": "https://github.com/bit-docs/bit-docs-html-toc#readme",
2828
"dependencies": {
2929
"can-assign": "^1.3.1",
30+
"can-define-lazy-value": "^1.1.0",
31+
"can-dom-mutate": "^1.3.6",
32+
"can-string": "^1.0.0",
3033
"can-view-target": "^4.1.2"
3134
},
3235
"devDependencies": {

safe-custom-element.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
function safeCustomElement(tag, constructor, prototype){
3+
prototype = prototype || constructor.prototype;
4+
var Element = function(){
5+
var result;
6+
if(typeof Reflect !== "undefined") {
7+
result = Reflect.construct(HTMLElement, [], new.target);
8+
} else {
9+
result = HTMLElement.apply(this, arguments);
10+
}
11+
constructor.apply(result, arguments);
12+
return result;
13+
};
14+
if(typeof HTMLElement !== undefined) {
15+
Element.prototype = Object.create(HTMLElement.prototype);
16+
}
17+
Object.getOwnPropertyNames(prototype).forEach(function(property){
18+
Object.defineProperty(Element.prototype, property,
19+
Object.getOwnPropertyDescriptor(prototype, property));
20+
});
21+
if(typeof customElements !== "undefined") {
22+
customElements.define(tag, Element);
23+
}
24+
25+
return Element;
26+
}
27+
28+
safeCustomElement.supported = (typeof Reflect !== "undefined") &&
29+
(typeof HTMLElement !== undefined) &&
30+
(typeof customElements !== "undefined");
31+
32+
33+
module.exports = safeCustomElement;

test/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
<html>
33
<head>
44
<title>bit-docs-html-toc</title>
5+
<style>
6+
.completed, .completed a {color: #dddddd;}
7+
.active, .active a {color: green;}
8+
</style>
59
</head>
610

711
<body>

test/toc-container-control-test.js

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ describe("TOCContainer", function() {
3333
new TOCContainer($el.get(0));
3434

3535
var $items = $("#toc-container ul");
36+
$("#toc-container li").removeAttr("class");
3637
assert.equal(
3738
$items.html(),
3839
[
@@ -42,44 +43,14 @@ describe("TOCContainer", function() {
4243
].join(""),
4344
"should create table of contents from the headings inside container"
4445
);
46+
var ids = $.makeArray($("article h2").map(function(i, element) {
47+
return element.id;
48+
}));
49+
50+
assert.deepEqual(ids, ["usage","install","configure"]);
4551

4652
// remove headings container from the DOM
4753
$("article").remove();
4854
});
4955

50-
it("reads the headings container selector from the element", function() {
51-
// set the container selector as a data-* attribute
52-
$el.attr(
53-
"data-headings-container-selector",
54-
".my-custom-container"
55-
);
56-
57-
var headings = [
58-
'<div class="my-custom-container">',
59-
"<h2>Usage</h2>",
60-
"<h2>Install</h2>",
61-
"<h2>Configure</h2>",
62-
"<h2>Configure</h2>",
63-
"</div>"
64-
];
65-
66-
// append the headings to the DOM and then instantiate the control
67-
$("body").append(headings.join(""));
68-
new TOCContainer($el.get(0));
69-
70-
var $items = $("#toc-container ul");
71-
assert.equal(
72-
$items.html(),
73-
[
74-
'<li><a href="#usage">Usage</a></li>',
75-
'<li><a href="#install">Install</a></li>',
76-
'<li><a href="#configure">Configure</a></li>',
77-
'<li><a href="#configure-1">Configure</a></li>'
78-
].join(""),
79-
"should create table of contents from the headings inside container"
80-
);
81-
82-
// remove headings container from the DOM
83-
$(".my-custom-container").remove();
84-
});
8556
});

test/toc-control-test.js

Lines changed: 83 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
var $ = require("jquery");
22
var assert = require("chai/chai").assert;
33
var TableOfContents = require("../toc-control");
4+
var safeCustomElement = require("../safe-custom-element");
45

56
require("steal-mocha");
67

78
describe("TableOfContents", function() {
9+
if(!safeCustomElement.supported) {
10+
return;
11+
}
812
var $el, $testArea;
913

1014
beforeEach(function() {
11-
$("body").append("<ul id=\"toc-test\"></ul>");
12-
13-
$el = $("#toc-test");
1415
$testArea = $("#test-area");
16+
1517
});
1618

1719
afterEach(function() {
18-
$el.remove();
1920
$testArea.empty();
21+
2022
});
2123

2224
it("makes a flat list from headings", function() {
@@ -27,15 +29,16 @@ describe("TableOfContents", function() {
2729
"<h2>Configure</h2>"
2830
];
2931

30-
$testArea.html(headings.join(""));
32+
$testArea.html("<article id='article'>"+headings.join("")+"</article>"+
33+
"<bit-toc child-tag='ul' headings-container-selector='#article' depth='1'>");
3134

32-
new TableOfContents($el.get(0), {
35+
/*new TableOfContents($el.get(0), {
3336
tagName: "ul",
3437
depth: 1,
3538
headingsContainerSelector: "#test-area"
36-
});
37-
38-
assert.equal($el.html(), [
39+
});*/
40+
$('bit-toc li').removeAttr("class"); // remove for nice html
41+
assert.equal(document.querySelector('bit-toc ul').innerHTML, [
3942
'<li><a href="#usage">Usage</a></li>',
4043
'<li><a href="#install">Install</a></li>',
4144
'<li><a href="#configure">Configure</a></li>',
@@ -53,13 +56,11 @@ describe("TableOfContents", function() {
5356
"<h2>Writing Modules</h2>",
5457
];
5558

56-
$testArea.html(headings.join(""));
5759

58-
new TableOfContents($el.get(0), {
59-
tagName: "ul",
60-
depth: 3,
61-
headingsContainerSelector: "#test-area"
62-
});
60+
$testArea.html("<article id='article'>"+headings.join("")+"</article>"+
61+
"<bit-toc child-tag='ul' headings-container-selector='#article' depth='3'>");
62+
63+
var $el = $('bit-toc>ul');
6364

6465
assert.equal($el.find(">li:eq(0) ul").length, 1, "bower has a nested list");
6566
assert.equal($el.find(">li:eq(1) ul").length, 2, "npm two nested lists");
@@ -76,18 +77,79 @@ describe("TableOfContents", function() {
7677
"<h2>Writing Modules</h2>"
7778
];
7879

79-
$testArea.html(headings.join(""));
80+
$testArea.html("<article id='article'>"+headings.join("")+"</article>"+
81+
"<bit-toc child-tag='ul' headings-container-selector='#article' depth='1'>");
8082

81-
new TableOfContents($el.get(0), {
82-
tagName: "ul",
83-
depth: 1,
84-
headingsContainerSelector: "#test-area"
85-
});
83+
var $el = $('bit-toc>ul');
84+
85+
$('bit-toc li').removeAttr("class"); // remove for nice html
8686

8787
assert.equal($el.html(), [
8888
'<li><a href="#bower">Bower</a></li>',
8989
'<li><a href="#npm">NPM</a></li>',
9090
'<li><a href="#writing-modules">Writing Modules</a></li>'
9191
].join(""));
9292
});
93+
94+
it("highlights what has been completed", function(){
95+
var headings = [
96+
"<h2>Bower</h2>",
97+
"<p>Install</p>",
98+
"<h2>NPM</h2>",
99+
"<p>Install</p>",
100+
"<h2>Configure</h2>",
101+
"<p>xyz</p>",
102+
"<h2>Writing Modules</h2>",
103+
"<p>writing modules</p>",
104+
"<h2>Extra</h2>",
105+
"<p>final</p>"
106+
];
107+
108+
$testArea.html("<article id='article'>"+headings.join("")+"</article>"+
109+
"<bit-toc headings-container-selector='#article'></bit-toc>");
110+
111+
$("article").css({
112+
position: "fixed",
113+
top: 0,
114+
height: 200,
115+
left: 200,
116+
width: 600,
117+
backgroundColor: "gray",
118+
overflowY: "auto"
119+
});
120+
121+
$("article p").css({
122+
height: "500px",
123+
border: "solid 1px red"
124+
});
125+
126+
$("bit-toc")[0].highlight();
127+
128+
function getCompletedAndActive(){
129+
var result = {completed: [], active: []}
130+
$("bit-toc li").each(function(i, node){
131+
if(node.classList.contains("completed")) {
132+
result.completed.push(node.textContent)
133+
}
134+
if(node.classList.contains("active")) {
135+
result.active.push(node.textContent)
136+
}
137+
});
138+
return result;
139+
}
140+
141+
assert.deepEqual(getCompletedAndActive(), {
142+
active: ["Bower"],
143+
completed: []
144+
}, "initialized correctly");
145+
146+
$("#article").scrollTop(600);
147+
$("bit-toc")[0].highlight(); // so we don't have to wait for the throttling
148+
149+
assert.deepEqual(getCompletedAndActive(), {
150+
active: ["NPM"],
151+
completed: ["Bower"]
152+
}, "initialized correctly");
153+
154+
});
93155
});

0 commit comments

Comments
 (0)