main interface ok

added grunt-svg2png and set svg 2 png fall back mixin
added bubbles and stars
added nav_pos move on chapter preview
This commit is contained in:
Bachir Soussi Chiadmi
2015-03-09 18:04:42 +01:00
parent 76c7154f4e
commit d5edfa75c8
810 changed files with 87625 additions and 320 deletions
+13 -1
View File
@@ -34,12 +34,24 @@ module.exports = function (grunt) {
},
dist: { src: 'css/*.css' }
},
svg2png: {
assets: {
// specify files in array format with multiple src-dest mapping
files: [
// rasterize all SVG files in "img" and its subdirectories to "img/png"
// { src: ['assets/img/*.svg'], dest: 'assets/img/png/' },
// rasterize SVG file to same directory
{ src: ['assets/img/*.svg'] }
]
}
}
});
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-postcss');
grunt.loadNpmTasks('grunt-svg2png');
grunt.registerTask('default', ['compass', 'postcss']);
grunt.registerTask('default', ['compass', 'postcss', 'svg2png']);
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="425"
height="425"
viewBox="0 0 425 425.00001"
id="svg15765"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="bubble-01.svg">
<defs
id="defs15767">
<radialGradient
id="SVGID_17_"
cx="-6706.2617"
cy="-2725.1895"
r="172.1931"
gradientTransform="matrix(1.2340828,0,0,1.2340828,8488.5815,4202.9728)"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
style="stop-color:#CBBBA0"
id="stop4338" />
<stop
offset="1"
style="stop-color:#cbbba0;stop-opacity:0"
id="stop4346" />
</radialGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="217.66355"
inkscape:cy="155.53537"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1155"
inkscape:window-x="-2"
inkscape:window-y="22"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid16331" />
</sodipodi:namedview>
<metadata
id="metadata15770">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-627.36216)">
<circle
style="fill:url(#SVGID_17_)"
cx="212.5"
cy="839.86212"
id="circle4348"
r="212.5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="885"
height="885"
viewBox="0 0 885.00001 885.00001"
id="svg16367"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="bubble-02.svg">
<defs
id="defs16369">
<radialGradient
id="SVGID_18_"
cx="-5383.5928"
cy="-1752.0127"
r="276.7793"
gradientTransform="matrix(1.5987427,0,0,1.5987428,9049.4803,3410.8796)"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
style="stop-color:#B6C38D"
id="stop4351" />
<stop
offset="1"
style="stop-color:#b6c38d;stop-opacity:0"
id="stop4359" />
</radialGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="436.0424"
inkscape:cy="437.90703"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1155"
inkscape:window-x="-2"
inkscape:window-y="22"
inkscape:window-maximized="1" />
<metadata
id="metadata16372">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-167.36216)">
<circle
style="opacity:0.86000001;fill:url(#SVGID_18_)"
cx="442.5"
cy="609.86218"
id="circle4361"
r="442.5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 15 KiB

@@ -46,7 +46,7 @@
spreadMethod="pad">
<stop
offset="0"
style="stop-color:#0066b1;stop-opacity:0.71"
style="stop-color:#0066b1;stop-opacity:0.506"
id="stop5359-9-7" />
<stop
offset="1"
@@ -62,8 +62,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="33.732485"
inkscape:cy="127.15041"
inkscape:cx="120.98441"
inkscape:cy="79.925779"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 14 KiB

@@ -45,7 +45,7 @@
fy="-2661.446">
<stop
offset="0"
style="stop-color:#cecd00;stop-opacity:0.698"
style="stop-color:#cecd00;stop-opacity:0.545"
id="stop5359-9-7" />
<stop
offset="1"
@@ -61,8 +61,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="23.883498"
inkscape:cy="84.471467"
inkscape:cx="74.012318"
inkscape:cy="82.956238"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@@ -45,7 +45,7 @@
fy="-2661.446">
<stop
offset="0"
style="stop-color:#62a530;stop-opacity:0.698"
style="stop-color:#62a530;stop-opacity:0.506"
id="stop5359-9-7" />
<stop
offset="1"
@@ -61,8 +61,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="80.45204"
inkscape:cy="85.986696"
inkscape:cx="105.07451"
inkscape:cy="83.713853"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@@ -45,7 +45,7 @@
fy="-2661.446">
<stop
offset="0"
style="stop-color:#33b4b5;stop-opacity:0.702"
style="stop-color:#33b4b5;stop-opacity:0.502"
id="stop5359-9-7" />
<stop
offset="1"
@@ -61,8 +61,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="79.694426"
inkscape:cy="100.63391"
inkscape:cx="78.305466"
inkscape:cy="88.51208"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@@ -45,7 +45,7 @@
fy="-2661.446">
<stop
offset="0"
style="stop-color:#af1380;stop-opacity:0.706"
style="stop-color:#af1380;stop-opacity:0.518"
id="stop5359-9-7" />
<stop
offset="1"
@@ -61,8 +61,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="64.542138"
inkscape:cy="93.815379"
inkscape:cx="92.70014"
inkscape:cy="89.522231"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -45,7 +45,7 @@
fy="-2661.446">
<stop
offset="0"
style="stop-color:#ea5b0c;stop-opacity:0.702"
style="stop-color:#ea5b0c;stop-opacity:0.502"
id="stop5359-9-7" />
<stop
offset="1"
@@ -61,8 +61,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="72.37082"
inkscape:cy="113.76589"
inkscape:cx="97.498364"
inkscape:cy="88.007"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -45,7 +45,7 @@
fy="-2661.446">
<stop
offset="0"
style="stop-color:#de003a;stop-opacity:0.7"
style="stop-color:#de003a;stop-opacity:0.502"
id="stop5359-9-7" />
<stop
offset="1"
@@ -61,8 +61,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="49.642388"
inkscape:cy="79.704082"
inkscape:cx="92.70014"
inkscape:cy="84.502307"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="10"
height="10"
viewBox="0 0 10 10"
id="svg16952"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="star.svg">
<defs
id="defs16954">
<linearGradient
inkscape:collect="always"
id="linearGradient17510">
<stop
style="stop-color:#ffffff;stop-opacity:0.69142854"
offset="0"
id="stop17512" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="1"
id="stop17514" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient17510"
id="radialGradient17516"
cx="5"
cy="1047.3622"
fx="5"
fy="1047.3622"
r="5"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="63.356767"
inkscape:cx="2.8741085"
inkscape:cy="6.230448"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1155"
inkscape:window-x="-2"
inkscape:window-y="22"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid17508" />
</sodipodi:namedview>
<metadata
id="metadata16957">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1042.3621)">
<circle
style="opacity:0.92142202;fill:url(#radialGradient17516);fill-opacity:1;stroke:none;stroke-width:0.13;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path17506"
cx="5"
cy="1047.3622"
r="5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

+294 -200
View File
@@ -3726,12 +3726,26 @@ p.heading {
font-size: 1.25em !important;
}
/* line 28, jee.scss */
/*
__ ________ __ _____ _______
/ |/ / _/ |/ // _/ | / / ___/
/ /|_/ // / | / / // |/ /\__ \
/ / / // / / |_/ // /| /___/ /
/_/ /_/___//_/|_/___/_/ |_//____/
*/
/*
___ ____ ____
/ | / __ \/ __ \
/ /| | / /_/ / /_/ /
/ ___ |/ ____/ ____/
/_/ |_/_/ /_/
*/
/* line 46, jee.scss */
html {
position: relative;
}
/* line 34, jee.scss */
/* line 52, jee.scss */
body {
position: relative;
-webkit-user-select: none;
@@ -3743,7 +3757,7 @@ body {
overflow: hidden;
}
/* line 43, jee.scss */
/* line 61, jee.scss */
#root {
position: relative;
width: 100%;
@@ -3857,8 +3871,9 @@ body {
opacity: 0;
}
}
/* line 91, jee.scss */
/* line 109, jee.scss */
#header {
z-index: 1;
position: absolute;
overflow: hidden;
width: 700px;
@@ -3870,18 +3885,18 @@ body {
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
/* line 104, jee.scss */
/* line 123, jee.scss */
#header h1 {
position: absolute;
width: 100%;
height: 100%;
}
/* line 107, jee.scss */
/* line 126, jee.scss */
#header h1 a {
display: block;
margin-top: -500%;
}
/* line 109, jee.scss */
/* line 128, jee.scss */
#header h1:after, #header h1:before {
content: "";
display: block;
@@ -3892,25 +3907,28 @@ body {
left: 0;
opacity: 0;
}
/* line 117, jee.scss */
/* line 136, jee.scss */
#header h1:before {
background: transparent url("../assets/img/logo.svg") no-repeat center center;
background: transparent url("../assets/img/logo.png") no-repeat center center;
background: none, url("../assets/img/logo.svg") no-repeat center center;
-webkit-animation: introLogo 8s linear 0s;
animation: introLogo 8s linear 0s;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
/* line 122, jee.scss */
/* line 141, jee.scss */
#header h1:after {
background: transparent url("../assets/img/logo-blured.svg") no-repeat center center;
background: transparent url("../assets/img/logo-blured.png") no-repeat center center;
background: none, url("../assets/img/logo-blured.svg") no-repeat center center;
-webkit-animation: introLogoBlured 8s linear 0s;
animation: introLogoBlured 8s linear 0s;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
/* line 129, jee.scss */
/* line 149, jee.scss */
#header h2 {
background: transparent url("../assets/img/slogan.svg") no-repeat center center;
background: transparent url("../assets/img/slogan.png") no-repeat center center;
background: none, url("../assets/img/slogan.svg") no-repeat center center;
position: absolute;
width: 100%;
height: 100%;
@@ -3920,13 +3938,13 @@ body {
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
/* line 133, jee.scss */
/* line 154, jee.scss */
#header h2 a {
display: block;
margin-top: -500%;
}
/* line 140, jee.scss */
/* line 161, jee.scss */
div.messages {
position: absolute;
top: 20px;
@@ -3937,7 +3955,7 @@ div.messages {
z-index: 1000;
}
/* line 148, jee.scss */
/* line 169, jee.scss */
#main {
position: absolute;
width: 100%;
@@ -3949,16 +3967,178 @@ div.messages {
| --| | | |__| | | -|__ | | __ -|_ _| | | | | | | | | __|
|_____|_____|_____|_____|__|__|_____| |_____| |_| |_|___|_____|____/|_____|
*/
/*
_____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____
| | | | _ | _ |_ _| __| __ | __| | __| __| | | __| __ | | | | | __|
| --| | | __| | | | __| -|__ | | | | __| | | | __| -|- -| | | | | __|
|_____|__|__|__|__|__| |_| |_____|__|__|_____| |_____|_____|_|___|_____|__|__|_____|__ _|_____|_____|
|__|
*/
}
/* line 153, jee.scss */
/* line 174, jee.scss */
#main > .region, #main > .region > .block-system, #main > .region > .block-system > .content {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
/* line 159, jee.scss */
/* line 189, jee.scss */
#main #node-2::after {
background: transparent url("../assets/img/bgd-sol.png") no-repeat center center;
background: none, url("../assets/img/bgd-sol.svg") no-repeat center center;
}
/* line 190, jee.scss */
#main #node-2, #main #node-2 a {
color: #b24c14;
}
/* line 191, jee.scss */
#main #node-2 h2.node-title, #main #node-2 h2.node-title a {
color: #d85509;
}
/* line 192, jee.scss */
#main #node-2 .field-name-field-vignette {
background: transparent url("../assets/img/shadow-sol.png") no-repeat center center;
background: none, url("../assets/img/shadow-sol.svg") no-repeat center center;
}
/* line 193, jee.scss */
#main #node-2 .line {
background-color: #ea5b0c;
}
/* line 197, jee.scss */
#main #node-3::after {
background: transparent url("../assets/img/bgd-dph.png") no-repeat center center;
background: none, url("../assets/img/bgd-dph.svg") no-repeat center center;
}
/* line 198, jee.scss */
#main #node-3, #main #node-3 a {
color: #686b00;
}
/* line 199, jee.scss */
#main #node-3 h2.node-title, #main #node-3 h2.node-title a {
color: #afaf00;
}
/* line 200, jee.scss */
#main #node-3 .field-name-field-vignette {
background: transparent url("../assets/img/shadow-dph.png") no-repeat center center;
background: none, url("../assets/img/shadow-dph.svg") no-repeat center center;
}
/* line 201, jee.scss */
#main #node-3 .line {
background-color: #cecd00;
}
/* line 205, jee.scss */
#main #node-4::after {
background: transparent url("../assets/img/bgd-sub.png") no-repeat center center;
background: none, url("../assets/img/bgd-sub.svg") no-repeat center center;
}
/* line 206, jee.scss */
#main #node-4, #main #node-4 a {
color: #b71330;
}
/* line 207, jee.scss */
#main #node-4 h2.node-title, #main #node-4 h2.node-title a {
color: #cd0734;
}
/* line 208, jee.scss */
#main #node-4 .field-name-field-vignette {
background: transparent url("../assets/img/shadow-sub.png") no-repeat center center;
background: none, url("../assets/img/shadow-sub.svg") no-repeat center center;
}
/* line 209, jee.scss */
#main #node-4 .line {
background-color: #de003a;
}
/* line 213, jee.scss */
#main #node-5::after {
background: transparent url("../assets/img/bgd-bc.png") no-repeat center center;
background: none, url("../assets/img/bgd-bc.svg") no-repeat center center;
}
/* line 214, jee.scss */
#main #node-5, #main #node-5 a {
color: #033d6f;
}
/* line 215, jee.scss */
#main #node-5 h2.node-title, #main #node-5 h2.node-title a {
color: #024b87;
}
/* line 216, jee.scss */
#main #node-5 .field-name-field-vignette {
background: transparent url("../assets/img/shadow-bc.png") no-repeat center center;
background: none, url("../assets/img/shadow-bc.svg") no-repeat center center;
}
/* line 217, jee.scss */
#main #node-5 .line {
background-color: #0066b1;
}
/* line 221, jee.scss */
#main #node-6::after {
background: transparent url("../assets/img/bgd-opp.png") no-repeat center center;
background: none, url("../assets/img/bgd-opp.svg") no-repeat center center;
}
/* line 222, jee.scss */
#main #node-6, #main #node-6 a {
color: #7f1965;
}
/* line 223, jee.scss */
#main #node-6 h2.node-title, #main #node-6 h2.node-title a {
color: #941b80;
}
/* line 224, jee.scss */
#main #node-6 .field-name-field-vignette {
background: transparent url("../assets/img/shadow-opp.png") no-repeat center center;
background: none, url("../assets/img/shadow-opp.svg") no-repeat center center;
}
/* line 225, jee.scss */
#main #node-6 .line {
background-color: #af1380;
}
/* line 229, jee.scss */
#main #node-7::after {
background: transparent url("../assets/img/bgd-dub.png") no-repeat center center;
background: none, url("../assets/img/bgd-dub.svg") no-repeat center center;
}
/* line 230, jee.scss */
#main #node-7, #main #node-7 a {
color: #22742c;
}
/* line 231, jee.scss */
#main #node-7 h2.node-title, #main #node-7 h2.node-title a {
color: #288d80;
}
/* line 232, jee.scss */
#main #node-7 .field-name-field-vignette {
background: transparent url("../assets/img/shadow-dub.png") no-repeat center center;
background: none, url("../assets/img/shadow-dub.svg") no-repeat center center;
}
/* line 233, jee.scss */
#main #node-7 .line {
background-color: #62a530;
}
/* line 237, jee.scss */
#main #node-8::after {
background: transparent url("../assets/img/bgd-juso.png") no-repeat center center;
background: none, url("../assets/img/bgd-juso.svg") no-repeat center center;
}
/* line 238, jee.scss */
#main #node-8, #main #node-8 a {
color: #0b7f8a;
}
/* line 239, jee.scss */
#main #node-8 h2.node-title, #main #node-8 h2.node-title a {
color: #009aa8;
}
/* line 240, jee.scss */
#main #node-8 .field-name-field-vignette {
background: transparent url("../assets/img/shadow-juso.png") no-repeat center center;
background: none, url("../assets/img/shadow-juso.svg") no-repeat center center;
}
/* line 241, jee.scss */
#main #node-8 .line {
background-color: #33b4b5;
}
/* line 251, jee.scss */
#main .node-chapitre.node-teaser {
z-index: 2;
position: absolute;
/*
_____ __________________ ___ _________________ __________________
@@ -3974,6 +4154,11 @@ div.messages {
|____/|_____|__| |__|__|_____|_____|_| |_|_|_|_____|____/|_____|
*/
opacity: 1;
-webkit-transition: 1s ease-out;
transition: 1s ease-out;
-webkit-transition-property: opacity;
transition-property: opacity;
/*
_____ _____ _____ _____ _____ _____ _ _ _ _____ _____ ____ _____
| _ | __ | __| | | | __| | | | | | | \| __|
@@ -3981,6 +4166,12 @@ div.messages {
|__| |__|__|_____|\___/|_____|_____|_____| |_|_|_|_____|____/|_____|
*/
/*
_____ _____ _____ _____ _____ _____ _____ _____ _____ _____ ____ _____
| | |_ _| | __| _ |_ _| __| | | | \| __|
| | | |- -| | | |- -| | | | | | | __| | | | | | | | | __|
|_|_|_|_____| |_| |_____|_____|__|__| |_| |_____| |_|_|_|_____|____/|_____|
*/
/*
_____________ ____________ ___ __ _____ __ _ __ __ _ _
/ ____/ ____/ | / / ____/ __ \/ | / / / ___/ _/_/___ ____ ____ (_)___ / /____ _________ ______/ /_(_) _____ | |
@@ -3990,7 +4181,7 @@ div.messages {
|_| /_/
*/
}
/* line 177, jee.scss */
/* line 274, jee.scss */
#main .node-chapitre.node-teaser h2.node-title {
-webkit-transform: none;
-ms-transform: none;
@@ -4004,11 +4195,11 @@ div.messages {
transition-property: transform;
z-index: 5;
}
/* line 184, jee.scss */
/* line 281, jee.scss */
#main .node-chapitre.node-teaser > .content {
position: relative;
}
/* line 185, jee.scss */
/* line 282, jee.scss */
#main .node-chapitre.node-teaser .texts {
opacity: 0;
height: 1px;
@@ -4019,7 +4210,7 @@ div.messages {
transition-property: opacity height;
position: absolute;
}
/* line 191, jee.scss */
/* line 288, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-partie {
opacity: 0;
position: absolute;
@@ -4028,12 +4219,12 @@ div.messages {
-webkit-transition-property: opacity -webkit-transform;
transition-property: opacity transform;
}
/* line 197, jee.scss */
/* line 294, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-partie:nth-child(2) {
z-index: 2;
opacity: 1;
}
/* line 201, jee.scss */
/* line 298, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-partie:nth-child(2) > .field-type-text {
opacity: 0;
-webkit-transition: 1s ease-out 0.9s;
@@ -4041,12 +4232,12 @@ div.messages {
-webkit-transition-property: opacity;
transition-property: opacity;
}
/* line 206, jee.scss */
/* line 303, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-partie:nth-child(2) > .field-name-field-vignette {
cursor: pointer;
z-index: 2;
}
/* line 209, jee.scss */
/* line 306, jee.scss */
#main .node-chapitre.node-teaser:after {
opacity: 0;
-webkit-transition: 2s ease-in;
@@ -4058,7 +4249,11 @@ div.messages {
bottom: 2px;
right: 2px;
}
/* line 228, jee.scss */
/* line 324, jee.scss */
#main .node-chapitre.node-teaser.previewed {
z-index: 100;
}
/* line 326, jee.scss */
#main .node-chapitre.node-teaser.previewed:after {
opacity: 1;
top: 2em;
@@ -4066,37 +4261,40 @@ div.messages {
right: -12em;
bottom: -30em;
}
/* line 235, jee.scss */
/* line 333, jee.scss */
#main .node-chapitre.node-teaser.previewed h2.node-title {
-webkit-transform: scale(2, 2);
-ms-transform: scale(2, 2);
transform: scale(2, 2);
}
/* line 236, jee.scss */
/* line 334, jee.scss */
#main .node-chapitre.node-teaser.previewed .texts {
opacity: 1;
height: 8em;
}
/* line 237, jee.scss */
/* line 335, jee.scss */
#main .node-chapitre.node-teaser.previewed .field-name-field-partie {
opacity: 1;
z-index: 0;
}
/* line 240, jee.scss */
/* line 338, jee.scss */
#main .node-chapitre.node-teaser.previewed .field-name-field-partie > .field {
opacity: 1;
z-index: -1;
cursor: default;
}
/* line 254, jee.scss */
/* line 348, jee.scss */
#main .node-chapitre.node-teaser.mitigated {
opacity: 0.3;
}
/* line 361, jee.scss */
#main .node-chapitre.node-teaser:after {
content: " ";
background-size: contain;
background-repeat: no-repeat;
background-size: contain !important;
position: absolute;
z-index: -1;
}
/* line 262, jee.scss */
/* line 368, jee.scss */
#main .node-chapitre.node-teaser h2.node-title {
font-family: "epflulb";
font-weight: normal;
@@ -4107,30 +4305,30 @@ div.messages {
z-index: 5;
}
@media only screen and (min-width: 64.063em) {
/* line 262, jee.scss */
/* line 368, jee.scss */
#main .node-chapitre.node-teaser h2.node-title {
font-size: 1.3em;
}
}
@media only screen and (min-width: 90.063em) {
/* line 262, jee.scss */
/* line 368, jee.scss */
#main .node-chapitre.node-teaser h2.node-title {
font-size: 1.8em;
}
}
/* line 282, jee.scss */
/* line 388, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-comprendre {
min-width: 16em;
}
/* line 283, jee.scss */
/* line 389, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-comprendre h1, #main .node-chapitre.node-teaser .field-name-field-comprendre h2, #main .node-chapitre.node-teaser .field-name-field-comprendre h3, #main .node-chapitre.node-teaser .field-name-field-comprendre h4, #main .node-chapitre.node-teaser .field-name-field-comprendre h5, #main .node-chapitre.node-teaser .field-name-field-comprendre h6 {
display: none !important;
}
/* line 285, jee.scss */
/* line 391, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-comprendre p {
margin: 0;
}
/* line 289, jee.scss */
/* line 395, jee.scss */
#main .node-chapitre.node-teaser ul.links {
display: block;
margin: 0;
@@ -4139,11 +4337,11 @@ div.messages {
position: relative;
width: 100%;
}
/* line 291, jee.scss */
/* line 397, jee.scss */
#main .node-chapitre.node-teaser ul.links li.node-readmore {
padding: 0;
}
/* line 293, jee.scss */
/* line 399, jee.scss */
#main .node-chapitre.node-teaser ul.links li.node-readmore a {
display: inline-block;
height: 25px;
@@ -4152,14 +4350,15 @@ div.messages {
color: #000 !important;
width: 8em;
text-align: left;
background: transparent url(../assets/img/readmore-btn.svg) no-repeat right center;
background: transparent url("../assets/img/readmore-btn.png") no-repeat right center;
background: none, url("../assets/img/readmore-btn.svg") no-repeat right center;
}
/* line 305, jee.scss */
/* line 412, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-partie {
clear: both;
padding-top: 1em;
}
/* line 309, jee.scss */
/* line 416, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-vignette {
position: relative;
float: left;
@@ -4169,31 +4368,29 @@ div.messages {
margin-bottom: 0;
margin-left: 0;
background-size: contain;
background-repeat: no-repeat;
background-origin: center center;
}
/* line 322, jee.scss */
/* line 429, jee.scss */
#main .node-chapitre.node-teaser .field-type-text {
min-width: 16em;
}
/* line 323, jee.scss */
/* line 430, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-titre {
font-family: "epflul";
font-size: 1.6em;
line-height: 1.1;
}
/* line 328, jee.scss */
/* line 435, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-sous-titre {
font-family: "epflul";
font-size: 1.4em;
line-height: 1.2;
}
/* line 333, jee.scss */
/* line 440, jee.scss */
#main .node-chapitre.node-teaser .field-name-field-description {
font-size: 0.88em;
line-height: 1.2;
}
/* line 339, jee.scss */
/* line 446, jee.scss */
#main .node-chapitre.node-teaser .line {
z-index: -1;
position: absolute;
@@ -4203,150 +4400,9 @@ div.messages {
-ms-transform-origin: top left;
transform-origin: top left;
width: 2px;
background-color: red;
opacity: 0.4;
}
/* line 358, jee.scss */
#main #node-2::after {
background-image: url(../assets/img/bgd-sol.svg);
}
/* line 359, jee.scss */
#main #node-2, #main #node-2 a {
color: #b24c14;
}
/* line 360, jee.scss */
#main #node-2 h2.node-title, #main #node-2 h2.node-title a {
color: #d85509;
}
/* line 361, jee.scss */
#main #node-2 .field-name-field-vignette {
background-image: url(../assets/img/shadow-sol.svg);
}
/* line 362, jee.scss */
#main #node-2 .line {
background-color: #ea5b0c;
}
/* line 366, jee.scss */
#main #node-3::after {
background-image: url(../assets/img/bgd-dph.svg);
}
/* line 367, jee.scss */
#main #node-3, #main #node-3 a {
color: #686b00;
}
/* line 368, jee.scss */
#main #node-3 h2.node-title, #main #node-3 h2.node-title a {
color: #afaf00;
}
/* line 369, jee.scss */
#main #node-3 .field-name-field-vignette {
background-image: url(../assets/img/shadow-dph.svg);
}
/* line 370, jee.scss */
#main #node-3 .line {
background-color: #cecd00;
}
/* line 374, jee.scss */
#main #node-4::after {
background-image: url(../assets/img/bgd-sub.svg);
}
/* line 375, jee.scss */
#main #node-4, #main #node-4 a {
color: #b71330;
}
/* line 376, jee.scss */
#main #node-4 h2.node-title, #main #node-4 h2.node-title a {
color: #cd0734;
}
/* line 377, jee.scss */
#main #node-4 .field-name-field-vignette {
background-image: url(../assets/img/shadow-sub.svg);
}
/* line 378, jee.scss */
#main #node-4 .line {
background-color: #de003a;
}
/* line 382, jee.scss */
#main #node-5::after {
background-image: url(../assets/img/bgd-bc.svg);
}
/* line 383, jee.scss */
#main #node-5, #main #node-5 a {
color: #033d6f;
}
/* line 384, jee.scss */
#main #node-5 h2.node-title, #main #node-5 h2.node-title a {
color: #024b87;
}
/* line 385, jee.scss */
#main #node-5 .field-name-field-vignette {
background-image: url(../assets/img/shadow-bc.svg);
}
/* line 386, jee.scss */
#main #node-5 .line {
background-color: #0066b1;
}
/* line 390, jee.scss */
#main #node-6::after {
background-image: url(../assets/img/bgd-opp.svg);
}
/* line 391, jee.scss */
#main #node-6, #main #node-6 a {
color: #7f1965;
}
/* line 392, jee.scss */
#main #node-6 h2.node-title, #main #node-6 h2.node-title a {
color: #941b80;
}
/* line 393, jee.scss */
#main #node-6 .field-name-field-vignette {
background-image: url(../assets/img/shadow-opp.svg);
}
/* line 394, jee.scss */
#main #node-6 .line {
background-color: #af1380;
}
/* line 398, jee.scss */
#main #node-7::after {
background-image: url(../assets/img/bgd-dub.svg);
}
/* line 399, jee.scss */
#main #node-7, #main #node-7 a {
color: #22742c;
}
/* line 400, jee.scss */
#main #node-7 h2.node-title, #main #node-7 h2.node-title a {
color: #288d80;
}
/* line 401, jee.scss */
#main #node-7 .field-name-field-vignette {
background-image: url(../assets/img/shadow-dub.svg);
}
/* line 402, jee.scss */
#main #node-7 .line {
background-color: #62a530;
}
/* line 406, jee.scss */
#main #node-8::after {
background-image: url(../assets/img/bgd-juso.svg);
}
/* line 407, jee.scss */
#main #node-8, #main #node-8 a {
color: #0b7f8a;
}
/* line 408, jee.scss */
#main #node-8 h2.node-title, #main #node-8 h2.node-title a {
color: #009aa8;
}
/* line 409, jee.scss */
#main #node-8 .field-name-field-vignette {
background-image: url(../assets/img/shadow-juso.svg);
}
/* line 410, jee.scss */
#main #node-8 .line {
background-color: #33b4b5;
}
/* line 413, jee.scss */
/* line 457, jee.scss */
#main .chapter-wrapper {
position: absolute;
top: 0;
@@ -4361,13 +4417,13 @@ div.messages {
/ __/ / /_/ / /_/ / / / / /___/ _, _/
/_/ \____/\____/ /_/ /_____/_/ |_|
*/
/* line 426, jee.scss */
/* line 470, jee.scss */
#footer {
position: fixed;
bottom: 0;
right: 0;
}
/* line 429, jee.scss */
/* line 473, jee.scss */
#footer .block {
display: inline-block;
vertical-align: top;
@@ -4380,7 +4436,7 @@ div.messages {
/ / / // / ___/ / /___
/_/ /_/___//____/\____/
*/
/* line 441, jee.scss */
/* line 485, jee.scss */
#fullscreen-btn {
position: fixed;
top: 20px;
@@ -4388,13 +4444,51 @@ div.messages {
z-index: 1000;
}
/* line 499, jee.scss */
.bubble-1 {
position: absolute;
z-index: 0;
display: block;
width: 425px;
height: 425px;
background: transparent url("../assets/img/bubble-01.png") no-repeat center center;
background: none, url("../assets/img/bubble-01.svg") no-repeat center center;
top: -200px;
left: -200px;
}
/* line 503, jee.scss */
.bubble-2 {
position: absolute;
z-index: 0;
display: block;
width: 885px;
height: 885px;
background: transparent url("../assets/img/bubble-02.png") no-repeat center center;
background: none, url("../assets/img/bubble-02.svg") no-repeat center center;
bottom: -400px;
right: -400px;
}
/* line 508, jee.scss */
.star {
position: absolute;
z-index: 0;
display: block;
width: 10px;
height: 10px;
opacity: 1;
background: transparent url("../assets/img/star.png") no-repeat center center;
background: none, url("../assets/img/star.svg") no-repeat center center;
}
/* ____ __________ __ ________
/ __ \/ ____/ __ )/ / / / ____/
/ / / / __/ / __ / / / / / __
/ /_/ / /___/ /_/ / /_/ / /_/ /
/_____/_____/_____/\____/\____/
*/
/* line 454, jee.scss */
/* line 522, jee.scss */
#fps {
position: fixed;
top: 20px;
@@ -4402,7 +4496,7 @@ div.messages {
z-index: 1000;
}
/* line 460, jee.scss */
/* line 528, jee.scss */
#nav-cursor {
position: absolute;
width: 6px;
+140 -72
View File
@@ -25,6 +25,24 @@ $column-gutter: rem-calc(20);
@import "misc.scss";
/*
__ ________ __ _____ _______
/ |/ / _/ |/ // _/ | / / ___/
/ /|_/ // / | / / // |/ /\__ \
/ / / // / / |_/ // /| /___/ /
/_/ /_/___//_/|_/___/_/ |_//____/
*/
@mixin bg-svg-png($img, $r:no-repeat, $x:center, $y:center) {
background: transparent url('../assets/img/#{$img}.png') $r $x $y;
background: none, url('../assets/img/#{$img}.svg') $r $x $y;
}
/*
___ ____ ____
/ | / __ \/ __ \
/ /| | / /_/ / /_/ /
/ ___ |/ ____/ ____/
/_/ |_/_/ /_/
*/
html{
position:relative;
// overflow:hidden;
@@ -89,6 +107,7 @@ body{
$animeLogoDuration:8s;
#header{
z-index:1;
position:absolute;
overflow:hidden;
width:700px;
@@ -115,19 +134,21 @@ $animeLogoDuration:8s;
opacity:0;
}
&:before{
background: transparent url('../assets/img/logo.svg') no-repeat center center;
@include bg-svg-png('logo');
animation: introLogo $animeLogoDuration linear 0s;
animation-fill-mode: forwards;
}
&:after{
background: transparent url('../assets/img/logo-blured.svg') no-repeat center center;
// background: transparent url('../assets/img/logo-blured.svg') no-repeat center center;
@include bg-svg-png('logo-blured');
animation: introLogoBlured $animeLogoDuration linear 0s;
animation-fill-mode: forwards;
}
}
h2{
background: transparent url('../assets/img/slogan.svg') no-repeat center center;
// background: transparent url('../assets/img/slogan.svg') no-repeat center center;
@include bg-svg-png('slogan');
position:absolute;
width:100%; height:100%;
a{display:block;margin-top:-500%;}
@@ -156,7 +177,79 @@ div.messages{
overflow:hidden;
}
/*
_____ _____ __ _____ _____ _____ _____ __ __ _____ _____ ____ _____
| | | | | | __ | __| | __ | | | | | | | \| __|
| --| | | |__| | | -|__ | | __ -|_ _| | | | | | | | | __|
|_____|_____|_____|_____|__|__|_____| |_____| |_| |_|___|_____|____/|_____|
*/
//SOL
#node-2{
&::after{ @include bg-svg-png('bgd-sol');}
&, a{color:$SOL-col-txt;}
h2.node-title{&,a{color:$SOL-color;}}
.field-name-field-vignette{@include bg-svg-png('shadow-sol');}
.line{background-color:$SOL-col-active;}
}
//DPH
#node-3{
&::after{ @include bg-svg-png('bgd-dph');}
&, a{color:$DPH-col-txt;}
h2.node-title{&,a{color:$DPH-color;}}
.field-name-field-vignette{@include bg-svg-png('shadow-dph');}
.line{background-color:$DPH-col-active;}
}
// SUB
#node-4{
&::after{ @include bg-svg-png('bgd-sub');}
&, a{color:$SUB-col-txt;}
h2.node-title{&,a{color:$SUB-color;}}
.field-name-field-vignette{@include bg-svg-png('shadow-sub');}
.line{background-color:$SUB-col-active;}
}
// BC
#node-5{
&::after{ @include bg-svg-png('bgd-bc');}
&, a{color:$BC-col-txt;}
h2.node-title{&,a{color:$BC-color;}}
.field-name-field-vignette{@include bg-svg-png('shadow-bc');}
.line{background-color:$BC-col-active;}
}
//OPP
#node-6{
&::after{ @include bg-svg-png('bgd-opp');}
&, a{color:$OPP-col-txt;}
h2.node-title{&,a{color:$OPP-color;}}
.field-name-field-vignette{@include bg-svg-png('shadow-opp');}
.line{background-color:$OPP-col-active;}
}
//DUB
#node-7{
&::after{ @include bg-svg-png('bgd-dub');}
&, a{color:$DUB-col-txt;}
h2.node-title{&,a{color:$DUB-color;}}
.field-name-field-vignette{@include bg-svg-png('shadow-dub');}
.line{background-color:$DUB-col-active;}
}
// JUSO
#node-8{
&::after{ @include bg-svg-png('bgd-juso');}
&, a{color:$JUSO-col-txt;}
h2.node-title{&,a{color:$JUSO-color;}}
.field-name-field-vignette{@include bg-svg-png('shadow-juso');}
.line{background-color:$JUSO-col-active;}
}
/*
_____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____
| | | | _ | _ |_ _| __| __ | __| | __| __| | | __| __ | | | | | __|
| --| | | __| | | | __| -|__ | | | | __| | | | __| -|- -| | | | | __|
|_____|__|__|__|__|__| |_| |_____|__|__|_____| |_____|_____|_|___|_____|__|__|_____|__ _|_____|_____|
|__|
*/
.node-chapitre.node-teaser{
z-index: 2;
position:absolute;
/*
@@ -174,6 +267,10 @@ div.messages{
|____/|_____|__| |__|__|_____|_____|_| |_|_|_|_____|____/|_____|
*/
opacity:1;
transition:1s ease-out;
transition-property:opacity;
h2.node-title{
transform:none;
transform-origin:bottom center;
@@ -225,6 +322,7 @@ div.messages{
*/
&.previewed{
z-index:100;
&:after{
opacity:1;
$pad:-2em;
@@ -241,6 +339,15 @@ div.messages{
}
}
/*
_____ _____ _____ _____ _____ _____ _____ _____ _____ _____ ____ _____
| | |_ _| | __| _ |_ _| __| | | | \| __|
| | | |- -| | | |- -| | | | | | | __| | | | | | | | | __|
|_|_|_|_____| |_| |_____|_____|__|__| |_| |_____| |_|_|_|_____|____/|_____|
*/
&.mitigated{
opacity:0.3;
}
/*
@@ -253,8 +360,7 @@ div.messages{
*/
&:after{ // background
content:" ";
background-size:contain;
background-repeat: no-repeat;
background-size:contain!important;
position:absolute;
z-index:-1;
}
@@ -297,7 +403,8 @@ div.messages{
font-weight: 900;
color:#000!important;
width:8em; text-align: left;
background: transparent url(../assets/img/readmore-btn.svg) no-repeat right center;
// background: transparent url(../assets/img/readmore-btn.svg) no-repeat right center;
@include bg-svg-png('readmore-btn', no-repeat, right, center);
}
}
}
@@ -316,8 +423,8 @@ div.messages{
margin-bottom:0;
margin-left:0;
background-size: contain;
background-repeat: no-repeat;
background-origin: center center;
// background-repeat: no-repeat;
// background-origin: center center;
}
.field-type-text{ min-width:16em; }
.field-name-field-titre{
@@ -341,75 +448,12 @@ div.messages{
position:absolute;
top:$shadow-size - 0.5em; left:$shadow-size+2.5em;
transform-origin:top left;
width:2px; background-color:red;
width:2px; //background-color:red;
opacity:0.4;
}
} // node-chapitre
/*
_____ _____ __ _____ _____ _____ _____ __ __ _____ _____ ____ _____
| | | | | | __ | __| | __ | | | | | | | \| __|
| --| | | |__| | | -|__ | | __ -|_ _| | | | | | | | | __|
|_____|_____|_____|_____|__|__|_____| |_____| |_| |_|___|_____|____/|_____|
*/
//SOL
#node-2{
&::after{ background-image : url(../assets/img/bgd-sol.svg); }
&, a{color:$SOL-col-txt;}
h2.node-title{&,a{color:$SOL-color;}}
.field-name-field-vignette{ background-image:url(../assets/img/shadow-sol.svg); }
.line{background-color:$SOL-col-active;}
}
//DPH
#node-3{
&::after{ background-image : url(../assets/img/bgd-dph.svg); }
&, a{color:$DPH-col-txt;}
h2.node-title{&,a{color:$DPH-color;}}
.field-name-field-vignette{ background-image:url(../assets/img/shadow-dph.svg); }
.line{background-color:$DPH-col-active;}
}
// SUB
#node-4{
&::after{ background-image : url(../assets/img/bgd-sub.svg); }
&, a{color:$SUB-col-txt;}
h2.node-title{&,a{color:$SUB-color;}}
.field-name-field-vignette{ background-image:url(../assets/img/shadow-sub.svg); }
.line{background-color:$SUB-col-active;}
}
// BC
#node-5{
&::after{ background-image : url(../assets/img/bgd-bc.svg); }
&, a{color:$BC-col-txt;}
h2.node-title{&,a{color:$BC-color;}}
.field-name-field-vignette{ background-image:url(../assets/img/shadow-bc.svg); }
.line{background-color:$BC-col-active;}
}
//OPP
#node-6{
&::after{ background-image : url(../assets/img/bgd-opp.svg); }
&, a{color:$OPP-col-txt;}
h2.node-title{&,a{color:$OPP-color;}}
.field-name-field-vignette{ background-image:url(../assets/img/shadow-opp.svg); }
.line{background-color:$OPP-col-active;}
}
//DUB
#node-7{
&::after{ background-image : url(../assets/img/bgd-dub.svg); }
&, a{color:$DUB-col-txt;}
h2.node-title{&,a{color:$DUB-color;}}
.field-name-field-vignette{ background-image:url(../assets/img/shadow-dub.svg); }
.line{background-color:$DUB-col-active;}
}
// JUSO
#node-8{
&::after{ background-image : url(../assets/img/bgd-juso.svg); }
&, a{color:$JUSO-col-txt;}
h2.node-title{&,a{color:$JUSO-color;}}
.field-name-field-vignette{ background-image:url(../assets/img/shadow-juso.svg); }
.line{background-color:$JUSO-col-active;}
}
.chapter-wrapper{
position:absolute;
top:0; left:0; bottom:0; right:0;
@@ -444,6 +488,30 @@ div.messages{
z-index: 1000;
}
@mixin bubble($w,$h,$bg){
position:absolute;
z-index:0;
display:block;
width:$w; height:$h;
// border:1px solid blue;
@include bg-svg-png($bg);
}
.bubble-1{
@include bubble(425px, 425px, 'bubble-01');
top:-200px; left:-200px;
}
.bubble-2{
@include bubble(885px, 885px, 'bubble-02');
bottom:-400px; right:-400px;
}
.star{
position:absolute;
z-index: 0; display:block;
width:10px; height:10px;
opacity:1;
@include bg-svg-png('star');
}
/* ____ __________ __ ________
/ __ \/ ____/ __ )/ / / / ____/
/ / / / __/ / __ / / / / / __
+142 -24
View File
@@ -30,10 +30,15 @@ jQuery(document).ready(function($) {
},
_center = {x:_container.w/2,y:_container.h/2},
_nav_pos = {x:0, y:0},
_mouse_down_pos = {x:0,y:0},
_prev_mouse_pos = {x:0,y:0},
_fps = 1000/12,
_dragging = false, _timeout_dragging;
var _bubbles = new Array(),
_stars = new Array();
function init(){
if(_debug)
initDebug();
@@ -47,6 +52,22 @@ jQuery(document).ready(function($) {
// launchIntoFullscreen(document.documentElement); // the whole page
launchIntoFullscreen(document.getElementById("root")); // any individual element
});
for (var i = 2; i > 0; i--) {
_bubbles.push($('<div>').addClass('bubble bubble-'+i).prependTo(_$container));
};
for (var i = 20; i > 0; i--) {
_stars.push(
$('<div>')
.addClass('star star-'+i)
.css({
left:randB(-400, _container.w+400),
top:randB(-400, _container.h+400)
})
.prependTo(_$container)
);
};
};
function initDebug(){
@@ -88,11 +109,18 @@ jQuery(document).ready(function($) {
function launchNav(){
$(document)
// DESKTOP EVENTS
/*
____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____
| \| __| __| | |_ _| | _ | | __| | | __| | |_ _| __|
| | | __|__ | -| | | | | | __| | __| | | __| | | | | | |__ |
|____/|_____|_____|__|__| |_| |_____|__| |_____|\___/|_____|_|___| |_| |_____|
*/
.bind('mousedown', function(e){
console.log('mousedown');
clearTimeout(_timeout_dragging);
// set initial cursor pos
_mouse_down_pos.x = e.clientX;
_mouse_down_pos.y = e.clientY;
updateNavPos(e.clientX, e.clientY, true);
$(this).bind('mousemove', function(e){
@@ -103,17 +131,25 @@ jQuery(document).ready(function($) {
// activate dragging if already activated
if(!_dragging){
_dragging = true;
window.requestAnimationFrame(moveNav);
startMoveNav();
}
})
.bind('mouseup', function(e){
console.log('mouseup');
stopMoveNav();
$(this).unbind('mousemove');
// close all preview
if(Math.abs(e.clientX - _mouse_down_pos.x) < 2
&& Math.abs(e.clientY - _mouse_down_pos.y) < 2)
for (var i = _chapitres_len - 1; i >= 0; i--)
_chapters[i].closePreview().unMitigate();
})
//
// TOUCH EVENTS - - - - - - - - - - - - - -
//
/*
_____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____
|_ _| | | | | | | | __| | | __| | |_ _| __|
| | | | | | | --| | | __| | | __| | | | | | |__ |
|_| |_____|_____|_____|__|__| |_____|\___/|_____|_|___| |_| |_____|
*/
.bind('touchstart', function(e){
console.log('touchstart');
clearTimeout(_timeout_dragging);
@@ -123,7 +159,7 @@ jQuery(document).ready(function($) {
// activate dragging if already activated
if(!_dragging){
_dragging = true;
window.requestAnimationFrame(moveNav);
startMoveNav();
}
})
.bind('touchmove', function(e){
@@ -141,15 +177,15 @@ jQuery(document).ready(function($) {
_nav_pos.x += x - _prev_mouse_pos.x;
_nav_pos.y += y - _prev_mouse_pos.y;
// constrain nav pos on container
_nav_pos.x = _nav_pos.x < -_center.x
? -_center.x
: _nav_pos.x > _center.x
? _center.x
_nav_pos.x = _nav_pos.x < -_center.x*2
? -_center.x*2
: _nav_pos.x > _center.x*2
? _center.x*2
: _nav_pos.x;
_nav_pos.y = _nav_pos.y < -_center.y
? -_center.y
: _nav_pos.y > _center.y
? _center.y
_nav_pos.y = _nav_pos.y < -_center.y*2
? -_center.y*2
: _nav_pos.y > _center.y*2
? _center.y*2
: _nav_pos.y;
}
_prev_mouse_pos.x = x;
@@ -160,6 +196,10 @@ jQuery(document).ready(function($) {
moveDebugCursor();
};
function startMoveNav(){
window.requestAnimationFrame(moveNav);
};
function moveNav(){
// console.log("moveNav");
if(!_dragging) return;
@@ -174,6 +214,23 @@ jQuery(document).ready(function($) {
_$header.css({
transform:"translate3d("+(_nav_pos.x)*0.2+"px, "+(_nav_pos.y)*0.2+"px,0)"
});
// bubbles and stars dont move so smoothly on tablette ...
// should keep it only on desktop
// move bubbles
// for (var i = _bubbles.length - 1; i >= 0; i--) {
// _bubbles[i].css({
// transform:"translate3d("+(_nav_pos.x)*0.4+"px, "+(_nav_pos.y)*0.4+"px,0)"
// });
// };
// move stars
// for (var i = _stars.length - 1; i >= 0; i--) {
// _stars[i].css({
// transform:"translate3d("+(_nav_pos.x)*-0.3+"px, "+(_nav_pos.y)*-0.3+"px,0)"
// });
// };
};
function stopMoveNav(){
@@ -185,6 +242,20 @@ jQuery(document).ready(function($) {
},3000);
};
function moveToChapter(chapter){
// fake a mousdown by providing first pos as current pos
_prev_mouse_pos.x = _nav_pos.x;
_prev_mouse_pos.y = _nav_pos.y;
// calculate the second pos of faked mousemove
var xl = _center.x - chapter.pos.x - chapter.geom.w/2;
var yl = 100 - chapter.pos.y;
updateNavPos(xl, yl, false);
startMoveNav();
stopMoveNav();
};
/*
________ __
/ ____/ /_ ____ _____ / /____ _____
@@ -200,19 +271,23 @@ jQuery(document).ready(function($) {
this.e = e;
this.$e = $(e);
this.nid = this.$e.attr("id").match(/^node-(\d+)/)[1];
this.$backdom = $('<div>').attr('id', 'backdom-'+this.nid).addClass('backdom').appendTo(_$body);
this.geom = {
base_a:base_a,
a:0,
r:0
r:0,
w:this.$e.outerWidth(true),
h:this.$e.outerHeight(true)
}
this.pos = {x:0,y:0};
this.trans = {x:0, y:0};
this.trans = {x:0, y:0,z:0};
this.ease = randB(0.05, 0.3);
//preview
this.is_previewed = false;
//mitigate
this.is_mitigated = false;
//parties
this.$parties = $('.field-name-field-partie', e);
this.parts_pos = {xs:new Array(), ys:new Array()};
@@ -248,10 +323,14 @@ jQuery(document).ready(function($) {
}
// change randomly radius
this.geom.r = randB(this.geom.r, this.geom.r*2);
if(this.i%2){
this.geom.r = randB(this.geom.r*2, this.geom.r*3);
}else{
this.geom.r = randB(this.geom.r, this.geom.r*2);
}
this.pos.x = Math.round(_center.x+this.geom.r * this.geom.c) - this.$e.outerWidth(true)/2;
this.pos.y = Math.round(_center.y+this.geom.r * -this.geom.s) - this.$e.outerHeight(true)/2;
this.pos.x = Math.round(_center.x+this.geom.r * this.geom.c) - this.geom.w/2;
this.pos.y = Math.round(_center.y+this.geom.r * -this.geom.s) - this.geom.h/2;
console.log('this', this);
this.$e.css({
@@ -265,6 +344,7 @@ jQuery(document).ready(function($) {
// click to preview chapter
$('h2.node-title, .field-name-field-partie:first>.field-name-field-vignette', this.$e)
.on('click', this, function(e){
// e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
e.data.preview(e);
@@ -284,25 +364,48 @@ jQuery(document).ready(function($) {
this.trans.x += (_nav_pos.x - this.trans.x)*this.ease;
this.trans.y += (_nav_pos.y - this.trans.y)*this.ease;
// this.trans.z = Math.floor(Math.sqrt(
// Math.pow(
// _center.x-(this.pos.x+this.trans.x)
// ,2
// )
// +
// Math.pow(
// _center.y-(this.pos.y+this.trans.y)
// ,2
// )
// ));
if(this.i === 0)
console.log(this.i+" this.trans.z", this.trans.z);
this.$e.css({
transform:'translate3d('+this.trans.x+'px,'+this.trans.y+'px,0)'
// scale:this.trans.z
});
};
Chapter.prototype.preview = function(e){
Chapter.prototype.preview = function(){
// don't relaunch preview more that one time
if(this.is_previewed) return;
console.log('preview', this.i);
this.unMitigate();
this.is_previewed = true;
// close other chapters
for (var i = _chapitres_len - 1; i >= 0; i--) {
for (var i = _chapitres_len - 1; i >= 0; i--)
if(i !== this.i)
_chapters[i].closePreview();
};
_chapters[i].closePreview().mitigate();
this.displayPreview();
moveToChapter(this);
};
Chapter.prototype.displayPreview = function(e){
// define randomly position of parties
this.resetPartsPos();
@@ -343,11 +446,26 @@ jQuery(document).ready(function($) {
};
Chapter.prototype.closePreview = function(){
if(!this.is_previewed) return this;
this.$e.removeClass('previewed')
.find('.field-name-field-partie')
.css({transform:"none"});
requestAnimationFrame(this.animeLines.bind(this));
this.is_previewed = false;
return this;
};
Chapter.prototype.mitigate = function(){
if(this.is_mitigated) return this;
this.$e.addClass('mitigated');
return this;
};
Chapter.prototype.unMitigate = function(){
if(this.is_mitigated) return this;
this.$e.removeClass('mitigated');
return this;
};
Chapter.prototype.drawLines = function(){
+21
View File
@@ -0,0 +1,21 @@
{
"name": "Jeunes et engagés",
"short_name": "Jee",
// "icons": [{
// "src": "icon/lowres",
// "sizes": "64x64",
// "type": "image/webp"
// }, {
// "src": "icon/hd_small",
// "sizes": "64x64"
// }, {
// "src": "icon/hd_hi",
// "sizes": "128x128",
// "density": 2
// }],
// "scope": "/racer/",
// "start_url": "/racer/start.html",
"display": "fullscreen",
"orientation": "landscape",
"chrome": { "navigation": true }
}
+18
View File
@@ -0,0 +1,18 @@
{
"curly": true,
"eqeqeq": true,
"immed": true,
"latedef": true,
"newcap": true,
"noarg": true,
"sub": true,
"undef": true,
"boss": true,
"eqnull": true,
"node": true,
"es5": true,
"globals": {
"phantom": true,
"window": true
}
}
+3
View File
@@ -0,0 +1,3 @@
node_modules
npm-debug.log
tmp
+59
View File
@@ -0,0 +1,59 @@
/*!
* grunt-svg2png
* https://github.com/dbushell/grunt-svg2png
*
* Copyright (c) 2013 David Bushell
* Licensed under The MIT License (MIT)
*/
'use strict';
module.exports = function(grunt)
{
grunt.initConfig({
jshint: {
all: [
'Gruntfile.js',
'tasks/**/*.js',
'<%= nodeunit.tests %>'
],
options: {
jshintrc: '.jshintrc'
}
},
clean: {
tests: ['test/**/*.png']
},
nodeunit: {
tests: ['test/*_test.js']
},
svg2png: {
all: {
files: [
{ cwd: 'test/svg/', src: ['**/*.svg'], dest: 'test/png/' }
]
}
}
});
grunt.loadTasks('tasks');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-nodeunit');
grunt.registerTask('unset_clearline', 'Unset stdout.clearLine for testing', function(){
process.stdout.clearLine = undefined;
});
grunt.registerTask('test', ['clean', 'svg2png', 'nodeunit']);
grunt.registerTask('test_noterminal', ['unset_clearline', 'test']);
grunt.registerTask('default', ['jshint', 'test']);
};
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013 David Bushell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+37
View File
@@ -0,0 +1,37 @@
grunt-svg2png
=============
Grunt plugin to rasterize SVG to PNG images using PhantomJS
## Getting Started
This plugin requires [Grunt](http://gruntjs.com/) `~0.4.1`
````javascript
// Gruntfile.js configuration
grunt.loadNpmTasks('grunt-svg2png');
grunt.initConfig({
svg2png: {
all: {
// specify files in array format with multiple src-dest mapping
files: [
// rasterize all SVG files in "img" and its subdirectories to "img/png"
{ cwd: 'img/', src: ['**/*.svg'], dest: 'img/png/' }
]
}
}
});
````
This task works well between [SVGO Grunt](https://github.com/svg/svgo-grunt) and [Grunt ImageOptim](https://github.com/JamieMason/grunt-imageoptim)!
## Updates
**2014-06-23** pulled in [path fix](https://github.com/dbushell/grunt-svg2png/pull/9) and option for [use case without terminal](https://github.com/dbushell/grunt-svg2png/pull/13). You may need to update your `files` config to include `cwd` and `dest` options.
* * *
Created by [David Bushell](http://dbushell.com) | [@dbushell](http://twitter.com/dbushell)
Copyright © 2013 David Bushell | MIT license
+1
View File
@@ -0,0 +1 @@
../phantomjs/bin/phantomjs
@@ -0,0 +1,3 @@
{
asi: false
}
@@ -0,0 +1,5 @@
/node_modules
/lib/phantom
/lib/location.js
/tmp
npm-debug.log
@@ -0,0 +1,7 @@
language: node_js
node_js:
- "0.10"
- "0.8"
before_install:
- npm install -g npm
@@ -0,0 +1,194 @@
Copyright 2012 The Obvious Corporation.
http://obvious.com/
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-------------------------------------------------------------------------
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
@@ -0,0 +1,199 @@
phantomjs
=========
An NPM wrapper for [PhantomJS](http://phantomjs.org/), headless webkit with JS API.
[![Build Status](https://travis-ci.org/Medium/phantomjs.svg?branch=master)](https://travis-ci.org/Medium/phantomjs)
Building and Installing
-----------------------
```shell
npm install phantomjs
```
Or grab the source and
```shell
node ./install.js
```
What this installer is really doing is just grabbing a particular "blessed" (by
this module) version of Phantom. As new versions of Phantom are released
and vetted, this module will be updated accordingly.
The package has been set up to fetch and run Phantom for MacOS (darwin),
Linux based platforms (as identified by nodejs), and -- as of version 0.2.0 --
Windows (thanks to [Domenic Denicola](https://github.com/domenic)). If you
spot any platform weirdnesses, let us know or send a patch.
### Custom binaries url
To use a mirror of the phantomjs binaries use npm config property `phantomjs_cdnurl`.
Default is `https://bitbucket.org/ariya/phantomjs/downloads`.
```shell
npm install phantomjs --phantomjs_cdnurl=http://cnpmjs.org/downloads
```
Or add property into your `.npmrc` file (https://www.npmjs.org/doc/files/npmrc.html)
```
phantomjs_cdnurl=http://cnpmjs.org/downloads
```
Another option is to use PATH variable `PHANTOMJS_CDNURL`.
```shell
PHANTOMJS_CDNURL=http://cnpmjs.org/downloads npm install phantomjs
```
Running
-------
```shell
bin/phantomjs [phantom arguments]
```
And npm will install a link to the binary in `node_modules/.bin` as
it is wont to do.
Running via node
----------------
The package exports a `path` string that contains the path to the
phantomjs binary/executable.
Below is an example of using this package via node.
```javascript
var path = require('path')
var childProcess = require('child_process')
var phantomjs = require('phantomjs')
var binPath = phantomjs.path
var childArgs = [
path.join(__dirname, 'phantomjs-script.js'),
'some other argument (passed to phantomjs script)'
]
childProcess.execFile(binPath, childArgs, function(err, stdout, stderr) {
// handle results
})
```
Versioning
----------
The major and minor number tracks the version of PhantomJS that will be
installed. The patch number is incremented when there is either an installer
update or a patch build of the phantom binary.
A Note on PhantomJS
-------------------
PhantomJS is not a library for NodeJS. It's a separate environment and code
written for node is unlikely to be compatible. In particular PhantomJS does
not expose a Common JS package loader.
This is an _NPM wrapper_ and can be used to conveniently make Phantom available
It is not a Node JS wrapper.
I have had reasonable experiences writing standalone Phantom scripts which I
then drive from within a node program by spawning phantom in a child process.
Read the PhantomJS FAQ for more details: http://phantomjs.org/faq.html
### Linux Note
An extra note on Linux usage, from the PhantomJS download page:
> This package is built on CentOS 5.8. It should run successfully on Lucid or
> more modern systems (including other distributions). There is no requirement
> to install Qt, WebKit, or any other libraries. It is however expected that
> some base libraries necessary for rendering (FreeType, Fontconfig) and the
> basic font files are available in the system.
Troubleshooting
---------------
##### Installation fails with `spawn ENOENT`
This is NPM's way of telling you that it was not able to start a `node` process. It usually means
Node is not on your PATH, or otherwise not properly installed.
##### Installation fails with `Error: EPERM` or `operation not permitted`
This error means that NPM was not able to install phantomjs to the file system. There are three
major reasons why this could happen:
- You don't have write access to the installation directory.
- The permissions in the NPM cache got messed up, and you need to run `npm cache clean` to fix them.
- You have over-zealous anti-virus software installed, and it's blocking file system writes.
##### Installation fails with `Error: read ECONNRESET` or `Error: connect ETIMEDOUT`
This error means that something went wrong with your internet connection, and the installer
was not able to download the PhantomJS binary for your platform. Please try again.
##### I tried again, but I get `ECONNRESET` or `ETIMEDOUT` consistently.
Do you live in China, or a country with an authoritarian government? We've seen problems where
the GFW or local ISP blocks bitbucket, preventing the installer from downloading the binary.
Try visiting the [the download page](http://cdn.bitbucket.org/ariya/phantomjs/downloads) manually.
If that page is blocked, you can try using a different CDN with the `PHANTOMJS_CDNURL`
env variable described above.
##### I am behind a corporate proxy that uses self-signed SSL certificates to intercept encrypted traffic.
You can tell NPM and the PhantomJS installer to skip validation of ssl keys with NPM's
[strict-ssl](https://www.npmjs.org/doc/misc/npm-config.html#strict-ssl) setting:
```
npm set strict-ssl false
```
WARNING: Turning off `strict-ssl` leaves you vulnerable to attackers reading
your encrypted traffic, so run this at your own risk!
##### I tried everything, but my network is b0rked. What do I do?
If you install PhantomJS manually, and put it on PATH, the installer will try to
use the manually-installed binaries.
##### I'm on Debian or Ubuntu, and the installer failed because it couldn't find `node`
Some Linux distros tried to rename `node` to `nodejs` due to a package
conflict. This is a non-portable change, and we do not try to support this. The
[official documentation](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os)
recommends that you run `apt-get install nodejs-legacy` to symlink `node` to `nodejs`
on those platforms, or many NodeJS programs won't work properly.
Contributing
------------
Questions, comments, bug reports, and pull requests are all welcome. Submit them at
[the project on GitHub](https://github.com/Obvious/phantomjs/). If you haven't contributed to an
[Obvious](http://github.com/Obvious/) project before please head over to the
[Open Source Project](https://github.com/Obvious/open-source#note-to-external-contributors) and fill
out an OCLA (it should be pretty painless).
Bug reports that include steps-to-reproduce (including code) are the
best. Even better, make them in the form of pull requests.
Author
------
[Dan Pupius](https://github.com/dpup)
([personal website](http://pupius.co.uk)), supported by
[The Obvious Corporation](http://obvious.com/).
License
-------
Copyright 2012 [The Obvious Corporation](http://obvious.com/).
Licensed under the Apache License, Version 2.0.
See the top-level file `LICENSE.txt` and
(http://www.apache.org/licenses/LICENSE-2.0).
@@ -0,0 +1,42 @@
#!/usr/bin/env node
/**
* Script that will execute the downloaded phantomjs binary. stdio are
* forwarded to and from the child process.
*
* The following is for an ugly hack to avoid a problem where the installer
* finds the bin script npm creates during global installation.
*
* {NPM_INSTALL_MARKER}
*/
var path = require('path')
var spawn = require('child_process').spawn
var binPath = require(path.join(__dirname, '..', 'lib', 'phantomjs')).path
var args = process.argv.slice(2)
// For Node 0.6 compatibility, pipe the streams manually, instead of using
// `{ stdio: 'inherit' }`.
var cp = spawn(binPath, args)
cp.stdout.pipe(process.stdout)
cp.stderr.pipe(process.stderr)
process.stdin.pipe(cp.stdin)
cp.on('error', function (err) {
console.error('Error executing phantom at', binPath)
console.error(err.stack)
})
cp.on('exit', function(code){
// Wait few ms for error to be printed.
setTimeout(function(){
process.exit(code)
}, 20)
});
process.on('SIGTERM', function() {
cp.kill('SIGTERM')
process.exit(1)
})
@@ -0,0 +1,354 @@
// Copyright 2012 The Obvious Corporation.
/*
* This simply fetches the right version of phantom for the current platform.
*/
'use strict'
var requestProgress = require('request-progress')
var progress = require('progress')
var AdmZip = require('adm-zip')
var cp = require('child_process')
var fs = require('fs-extra')
var helper = require('./lib/phantomjs')
var kew = require('kew')
var npmconf = require('npmconf')
var path = require('path')
var request = require('request')
var url = require('url')
var util = require('util')
var which = require('which')
var cdnUrl = process.env.npm_config_phantomjs_cdnurl || process.env.PHANTOMJS_CDNURL || 'https://bitbucket.org/ariya/phantomjs/downloads'
var downloadUrl = cdnUrl + '/phantomjs-' + helper.version + '-'
var originalPath = process.env.PATH
// If the process exits without going through exit(), then we did not complete.
var validExit = false
process.on('exit', function () {
if (!validExit) {
console.log('Install exited unexpectedly')
exit(1)
}
})
// NPM adds bin directories to the path, which will cause `which` to find the
// bin for this package not the actual phantomjs bin. Also help out people who
// put ./bin on their path
process.env.PATH = helper.cleanPath(originalPath)
var libPath = path.join(__dirname, 'lib')
var pkgPath = path.join(libPath, 'phantom')
var phantomPath = null
var tmpPath = null
// If the user manually installed PhantomJS, we want
// to use the existing version.
//
// Do not re-use a manually-installed PhantomJS with
// a different version.
//
// Do not re-use an npm-installed PhantomJS, because
// that can lead to weird circular dependencies between
// local versions and global versions.
// https://github.com/Obvious/phantomjs/issues/85
// https://github.com/Medium/phantomjs/pull/184
var whichDeferred = kew.defer()
which('phantomjs', whichDeferred.makeNodeResolver())
whichDeferred.promise
.then(function (result) {
phantomPath = result
// Horrible hack to avoid problems during global install. We check to see if
// the file `which` found is our own bin script.
if (phantomPath.indexOf(path.join('npm', 'phantomjs')) !== -1) {
console.log('Looks like an `npm install -g` on windows; unable to check for already installed version.')
throw new Error('Global install')
}
var contents = fs.readFileSync(phantomPath, 'utf8')
if (/NPM_INSTALL_MARKER/.test(contents)) {
console.log('Looks like an `npm install -g`; unable to check for already installed version.')
throw new Error('Global install')
} else {
var checkVersionDeferred = kew.defer()
cp.execFile(phantomPath, ['--version'], checkVersionDeferred.makeNodeResolver())
return checkVersionDeferred.promise
}
})
.then(function (stdout) {
var version = stdout.trim()
if (helper.version == version) {
writeLocationFile(phantomPath);
console.log('PhantomJS is already installed at', phantomPath + '.')
exit(0)
} else {
console.log('PhantomJS detected, but wrong version', stdout.trim(), '@', phantomPath + '.')
throw new Error('Wrong version')
}
})
.fail(function (err) {
// Trying to use a local file failed, so initiate download and install
// steps instead.
var npmconfDeferred = kew.defer()
npmconf.load(npmconfDeferred.makeNodeResolver())
return npmconfDeferred.promise
})
.then(function (conf) {
tmpPath = findSuitableTempDirectory(conf)
// Can't use a global version so start a download.
if (process.platform === 'linux' && process.arch === 'x64') {
downloadUrl += 'linux-x86_64.tar.bz2'
} else if (process.platform === 'linux') {
downloadUrl += 'linux-i686.tar.bz2'
} else if (process.platform === 'darwin' || process.platform === 'openbsd' || process.platform === 'freebsd') {
downloadUrl += 'macosx.zip'
} else if (process.platform === 'win32') {
downloadUrl += 'windows.zip'
} else {
console.error('Unexpected platform or architecture:', process.platform, process.arch)
exit(1)
}
var fileName = downloadUrl.split('/').pop()
var downloadedFile = path.join(tmpPath, fileName)
// Start the install.
if (!fs.existsSync(downloadedFile)) {
console.log('Downloading', downloadUrl)
console.log('Saving to', downloadedFile)
return requestBinary(getRequestOptions(conf), downloadedFile)
} else {
console.log('Download already available at', downloadedFile)
return downloadedFile
}
})
.then(function (downloadedFile) {
return extractDownload(downloadedFile)
})
.then(function (extractedPath) {
return copyIntoPlace(extractedPath, pkgPath)
})
.then(function () {
var location = process.platform === 'win32' ?
path.join(pkgPath, 'phantomjs.exe') :
path.join(pkgPath, 'bin' ,'phantomjs')
var relativeLocation = path.relative(libPath, location)
writeLocationFile(relativeLocation)
// Ensure executable is executable by all users
fs.chmodSync(location, '755')
console.log('Done. Phantomjs binary available at', location)
exit(0)
})
.fail(function (err) {
console.error('Phantom installation failed', err, err.stack)
exit(1)
})
function writeLocationFile(location) {
console.log('Writing location.js file')
if (process.platform === 'win32') {
location = location.replace(/\\/g, '\\\\')
}
fs.writeFileSync(path.join(libPath, 'location.js'),
'module.exports.location = "' + location + '"')
}
function exit(code) {
validExit = true
process.env.PATH = originalPath
process.exit(code || 0)
}
function findSuitableTempDirectory(npmConf) {
var now = Date.now()
var candidateTmpDirs = [
process.env.TMPDIR || process.env.TEMP || npmConf.get('tmp'),
'/tmp',
path.join(process.cwd(), 'tmp')
]
for (var i = 0; i < candidateTmpDirs.length; i++) {
var candidatePath = path.join(candidateTmpDirs[i], 'phantomjs')
try {
fs.mkdirsSync(candidatePath, '0777')
// Make double sure we have 0777 permissions; some operating systems
// default umask does not allow write by default.
fs.chmodSync(candidatePath, '0777')
var testFile = path.join(candidatePath, now + '.tmp')
fs.writeFileSync(testFile, 'test')
fs.unlinkSync(testFile)
return candidatePath
} catch (e) {
console.log(candidatePath, 'is not writable:', e.message)
}
}
console.error('Can not find a writable tmp directory, please report issue ' +
'on https://github.com/Obvious/phantomjs/issues/59 with as much ' +
'information as possible.')
exit(1)
}
function getRequestOptions(conf) {
var strictSSL = conf.get('strict-ssl')
if (process.version == 'v0.10.34') {
console.log('Node v0.10.34 detected, turning off strict ssl due to https://github.com/joyent/node/issues/8894')
strictSSL = false
}
var options = {
uri: downloadUrl,
encoding: null, // Get response as a buffer
followRedirect: true, // The default download path redirects to a CDN URL.
headers: {},
strictSSL: strictSSL
}
var proxyUrl = conf.get('https-proxy') || conf.get('http-proxy') || conf.get('proxy')
if (proxyUrl) {
// Print using proxy
var proxy = url.parse(proxyUrl)
if (proxy.auth) {
// Mask password
proxy.auth = proxy.auth.replace(/:.*$/, ':******')
}
console.log('Using proxy ' + url.format(proxy))
// Enable proxy
options.proxy = proxyUrl
// If going through proxy, use the user-agent string from the npm config
options.headers['User-Agent'] = conf.get('user-agent')
}
// Use certificate authority settings from npm
var ca = conf.get('ca')
if (ca) {
console.log('Using npmconf ca')
options.ca = ca
}
return options
}
function requestBinary(requestOptions, filePath) {
var deferred = kew.defer()
var count = 0
var notifiedCount = 0
var writePath = filePath + '-download-' + Date.now()
console.log('Receiving...')
var bar = null
requestProgress(request(requestOptions, function (error, response, body) {
console.log('');
if (!error && response.statusCode === 200) {
fs.writeFileSync(writePath, body)
console.log('Received ' + Math.floor(body.length / 1024) + 'K total.')
fs.renameSync(writePath, filePath)
deferred.resolve(filePath)
} else if (response) {
console.error('Error requesting archive.\n' +
'Status: ' + response.statusCode + '\n' +
'Request options: ' + JSON.stringify(requestOptions, null, 2) + '\n' +
'Response headers: ' + JSON.stringify(response.headers, null, 2) + '\n' +
'Make sure your network and proxy settings are correct.\n\n' +
'If you continue to have issues, please report this full log at ' +
'https://github.com/Medium/phantomjs')
exit(1)
} else if (error && error.stack && error.stack.indexOf('SELF_SIGNED_CERT_IN_CHAIN') != -1) {
console.error('Error making request, SELF_SIGNED_CERT_IN_CHAIN. Please read https://github.com/Medium/phantomjs#i-am-behind-a-corporate-proxy-that-uses-self-signed-ssl-certificates-to-intercept-encrypted-traffic')
exit(1)
} else if (error) {
console.error('Error making request.\n' + error.stack + '\n\n' +
'Please report this full log at https://github.com/Medium/phantomjs')
exit(1)
} else {
console.error('Something unexpected happened, please report this full ' +
'log at https://github.com/Medium/phantomjs')
exit(1)
}
})).on('progress', function (state) {
if (!bar) {
bar = new progress(' [:bar] :percent :etas', {total: state.total, width: 40})
}
bar.curr = state.received
bar.tick(0)
})
return deferred.promise
}
function extractDownload(filePath) {
var deferred = kew.defer()
// extract to a unique directory in case multiple processes are
// installing and extracting at once
var extractedPath = filePath + '-extract-' + Date.now()
var options = {cwd: extractedPath}
fs.mkdirsSync(extractedPath, '0777')
// Make double sure we have 0777 permissions; some operating systems
// default umask does not allow write by default.
fs.chmodSync(extractedPath, '0777')
if (filePath.substr(-4) === '.zip') {
console.log('Extracting zip contents')
try {
var zip = new AdmZip(filePath)
zip.extractAllTo(extractedPath, true)
deferred.resolve(extractedPath)
} catch (err) {
console.error('Error extracting zip')
deferred.reject(err)
}
} else {
console.log('Extracting tar contents (via spawned process)')
cp.execFile('tar', ['jxf', filePath], options, function (err, stdout, stderr) {
if (err) {
console.error('Error extracting archive')
deferred.reject(err)
} else {
deferred.resolve(extractedPath)
}
})
}
return deferred.promise
}
function copyIntoPlace(extractedPath, targetPath) {
console.log('Removing', targetPath)
return kew.nfcall(fs.remove, targetPath).then(function () {
// Look for the extracted directory, so we can rename it.
var files = fs.readdirSync(extractedPath)
for (var i = 0; i < files.length; i++) {
var file = path.join(extractedPath, files[i])
if (fs.statSync(file).isDirectory() && file.indexOf(helper.version) != -1) {
console.log('Copying extracted folder', file, '->', targetPath)
return kew.nfcall(fs.move, file, targetPath)
}
}
console.log('Could not find extracted file', files)
throw new Error('Could not find extracted file')
})
}
@@ -0,0 +1 @@
module.exports.location = "phantom/bin/phantomjs"
@@ -0,0 +1,368 @@
Please see also http://phantomjs.org/releases.html.
2014-10-22: Version 1.9.8
* Change default SSL protocol to TLSv1 to address POODLE (issue 12655)
To use the old default protocol of SSLv3 which is vulnerable to POODLE
add the --ssl-protocol=SSLv3 flag. Reference: http://poodlebleed.com/
* Fixed building on OS X 10.10 Yosemite (issue 12622)
* Backported crash fix when exit (issue 11642, 12431)
2014-01-25: Version 1.9.7
* Reverted to GhostDriver 1.1.0 instead of 1.1.1 (issue 11915)
* Fixed another warning of obsolete userSpaceScaleFactor on OS X 10.9 (issue 11612)
2014-01-20: Version 1.9.6
* Updated GhostDriver to version 1.1.1 (issue 11877, 11893)
2014-01-19: Version 1.9.3
* Fixed CoreText performance note on OS X 10.9 (issue 11418)
* Fixed warning of obsolete userSpaceScaleFactor on OS X 10.9 (issue 11612)
2013-09-06: Version 1.9.2
* Fixed graphical artifacts with transparent background on Windows (issue 11276, 11007, 11366)
* Updated GhostDriver to version 1.0.4 (issue 11452)
2013-06-04: Version 1.9.1
Critical bug fixes:
* Fixed problems with specifying proxy server (issue 10811, 11117)
* Fixed UTF-8 encoding with system.stdout and system.stderr (issue 11162)
* Ensured that onResourceReceived will be always invoked (issue 11163)
* Fixed module loading from an absolute path on Windows (issue 11165)
* Fixed typo in the command-line option for setting the cache size (11219)
* Fixed possible crash when handling network requests (issue 11252, 11388)
2013-03-20: Version 1.9.0 "Sakura"
New features
* Added spawn and execFile to execute external programs (issue 10219)
* Added the ability to abort network requests (issue 10230)
* Added system access to stdin, stdout, and stderr (issue 10333)
* Added support for custom CA certificates location (issue 10916)
* Added seek function to the File stream (issue 10937)
* Implemented file read for a specified number of bytes (issue 10938)
* Added a callback to handle network error (issue 10954, 10997)
* Added custom encoding support when opening a page (issue 11043)
* Implemented require.stub() support for a factory function (issue 11044)
* Added page loading indicator and progress (issue 11091)
* Added a timeout option for network requests (issue 11129)
Improvements
* Fixed the build on FreeBSD (issue 10597)
* Ensured a consistent 72 dpi for Linux headless rendering (issue 10659)
* Fixed possible PDF error due to invalid CreationDate field (issue 10663)
* Fixed crash when uploading non existing files (issue 10941)
* Improved the autocomplete internal of the interactive/REPL mode (issue 10943)
* Fixed possible crash when accessing inline frames (issue 10947)
* Changed Linux binary package setup to be built on CentOS 5 (issue 10963)
* Extended SSL ignore setting to synchronous XHR (issue 10985)
* Added convenient constants for modifier keys (issue 11056)
* Fixed incorrect date handling in the cookies (issue 11068)
* Updated GhostDriver to version 1.0.3 (issue 11146)
Examples
* Fixed invalid data URI in the netsniff example (issue 10740)
* Implemented a new weather example (issue 10794)
* Fixed rendering issues in render_multi_url (issue 11021)
* Fixed proper event sequence in page_events example (issue 11028)
* Miscellanous tweaks (issue 11082)
2013-03-02: Version 1.8.2
Critical bug fixes:
* Fixed possible PDF error due to invalid CreationDate field (issue 663)
* Fixed crash when uploading non existing files (issue 941)
* Fixed possible crash when accessing inline frames (issue 947)
* Extended SSL ignore setting to synchronous XHR (issue 985)
* Fixed incorrect date handling in the cookies (issue 1068)
2013-01-06: Version 1.8.1
Critical bug fix:
* Mac OS X: Fix possible crash when using some TrueType fonts (issue 690)
2012-12-21: Version 1.8.0 "Blue Winter Rose"
New features
* Integrated GhostDriver as the WebDriver implementation (issue 49)
* Added an option to specify the SSL protocol (issue 174)
* Added encoding support for WebServer's response (issue 505)
* Added process ID (PID) to the System module (issue 769)
* Added properties to obtain page and frame title (issue 799)
* Added page navigation methods (issue 808)
* Added support for modifier keys in keyboard events (issue 835)
* Added onFilePicker callback for more generic file upload API (issue 843)
* Added the ability to set the page content and location (issue 909)
Improvements
* Fixed date parsing in ISO8601 format (issue 187, 267)
* Fixed window.location (issue 530, 632)
* Deregistered multiple callback handler (issue 807)
* Fixed sending of double-click events (issue 848)
* Increases maximum number of redirects (issue 849)
* Fixed keycodes sent for lowercase characters (issue 852)
* Fixed a regression in table row page break (issue 880)
* Completed the CoffeeScript version of the examples (issue 907)
* Updated Qt to version 4.8.4 (issue 918)
* Fixed potential hang in some example scripts (issue 922)
2012-09-22: Version 1.7.0 "Blazing Star"
New features
* Added a module system modelled after CommonJS/Node.js (issue 47)
* Added support for window pop-up (issue 151)
* Static build on Linux (issue 413)
* Added run-time detection of SSL support (issue 484)
* Added more events support (issue 492, 712)
* Added support for disabling automatic proxy detection (issue 580)
* Provided page closing callback (issue 678)
* Added methods to access URL, frames URL, frame Content (issue 758)
* Added more cookies-related API (issue 761)
Improvements
* Refactored command-line options handling (issue 55)
* Improved the workflow for producing release builds (issue 599)
* Improved cookies API and implementation (issue 603, 761)
* Improved frame switching API (issue 654)
* Fixed iframe handling regression (issue 683)
* Fixed OS version number with Windows 8 and Mountain Lion (issue 684, 688)
* Fixed HAR navigation info in the netsniff example (issue 733)
* Fixed compile warnings with Visual Studio (issue 744)
* Removed hacks for static linking on Windows (issue 753)
* Added ICO image handling on Windows (issue 779)
* Fixed font antialiasing on Windows (issue 785)
* Improved Jasmine test runner for Jasmine 1.2 (issue 792)
2012-07-22: Version 1.6.1
Bug fixes
* Don't build the deploy in debug mode (issue 599)
* Fixed building on Windows (issue 424)
* Fixed remote inspector when building statically (issue 430)
2012-06-20: Version 1.6.0 "Lavender"
New features
* Added support for passing arguments to WebPage's evaluate (issue 132)
* Added callbacks for JavaScript onConfirm and onPrompt (issue 133)
* Added stack trace when error occurs (issue 166)
* Added support for local storage path and quota (issue 300)
* Added initial support for cookies handling (issue 354)
* Added support for header footer when printing the page (issue 410, 512)
* Added headers support in the loading request (issue 452)
* Added support to render the web page as base64-encoded string (issue 547)
* Added hooks for navigation event (issue 562)
* Added command-line option to show debug messages (issue 575)
* Added support for the zoom factor for web page rendering (issue 579)
* Added crash reporter for Mac OS X and Linux, based on Google Breakpad (issue 576)
* Added 'os' object to the system module (issue 585)
* Added support for asynchronous evaluation (issue 593)
Improvements
* Fixed remote debugging to work on Mac OS X and Windows (issue 430)
* Fixed web server getting the dropped connection for empty response (issue 451)
* Fixed text rendered as boxes (squares) on headless Linux (issue 460)
* Updated Qt to version 4.8.2 (issue 495)
* Updated CoffeeScript compiler to version 1.3.3 (issue 496)
* Fixed the build script to detect and use MAKEFLAGS (issue 503)
* Fixed the build script to properly pass Qt config flags (issue 507)
* Changed Info.plist to be embedded in Mac OS X executable (issue 528)
* Fixed wrong module require in the imagebin example (issue 536)
* Fixed example scripts to exit with the right exit code (issue 544)
* Fixed build failure with glib 2.31.0+ (issue 559)
* Fixed error handler failures in some cases (issue 589)
* Fixed Twitter-related examples to work with the new site (issue 609)
2012-03-20: Version 1.5.0 "Ghost Flower"
New features
* Added interactive mode, also known as REPL (issue 252)
* Added setting for web security, to allow cross domain XHR (issue 28)
* Added error handler for WebPage object (issue 166)
* Added support for custom HTTP header in the network request (issue 77)
* Added support for read write encoding in the file system module (issue 367)
* Added remote debugging support on Linux (issue 6)
* Added support for proxy authentication (issue 105)
* Added System module, to retrieve environment variables (issue 271) and arguments (issue 276)
* Added fs.readLink function (issue 329)
* Added support for reading and writing binary data (issue 400)
* Added support to retrieve request data in the WebServer? module (issue 340)
* Added support for individual top/bottom/left/right print margins (issue 388)
* Added command-line option --help (issue 347)
* Added short command-line options -v and -h (issue 408)
* Removed support for Flash and other plugins (issue 418)
Bug fixes
* Fixed multiple console.log arguments (issue 36)
* Fixed file upload (issue 307)
* Fixed the web server instance to be asynchronous (issue 326) and still support Keep Alive (issue 416)
* Workaround Qt 4.8.0 crash due to empty URL scheme (issue 365)
* Fixed a Content-Type problem where POST does not work (issue 337)
* Fixed reading body request in the web server even without specific Content-Type (issue 439)
* Fixed Jasmine test runner with Jasmine 1.1 (issue 402)
* Fixed request URL formatting in the web server (issue 437)
* Don't display debugging and warning messages (issue 323)
2011-12-31: Version 1.4.1
Bug fixes
* Fix setting the proxy type (issue 266)
* Workaround for file upload regression (issue 307)
* Fix extraneous messsages in non-debug mode (issue 323)
2011-12-22: Version 1.4.0 "Glory of the Snow"
New features
* Added embedded HTTP server (issue 115)
* Added convenient build script for Linux (issue 197)
* Added support for SOCKS5 proxy (issue 266)
* Updated CoffeeScript compiler to version 1.2 (issue 312)
Bug fixes
* Fix potential crash in QUrl with Qt 4.8 (issue 304)
* Fix bug in CookieJar with QSettings and string (PyPhantomJS issue 10)
* Prevent showing the icon on Mac OS X Dock (issue 281)
Examples
* Added a new example to detect browsers sniffing (issue 263)
* Added HTTP server example (issue 115)
2011-09-23: Version 1.3.0 "Water Lily"
Bug fixes
* Fixed open() and POST method, without specifying the finished handler
* Fixed script execution warning dialog (issue 165)
* Added WebPage.release() to free the web page from memory (issue 154)
* Added special handling of about:blank (issue 235)
* Made a separate network access manager for each page (issue 190)
New features
* Introduced file system API based on CommonJS Filesystem proposal (issue 129)
* Added support for persistent cookies (issue 91)
* Added event handling, currently only for mouse events (issue 234)
* Added page scroll position (issue 162)
* Added HTTP authentication support (issue 45)
* Added callback for page initialization (issue 143)
* Added support to specify script and output encoding (issue 186)
* Added option to allow local content to do cross-domain access (issue 28)
* Added support to apply configurations from a JSON file (issue 180)
* Added a convenient WebPage initialization construction (issue 206)
* Added option to limit the size of disk cache (issue 220)
Examples
* Added a new example on using Modernizr to detect features (issue 144)
* Fixed pizza.js example to use Mobile Yelp (issue 200)
* Fixed netsniff.coffee example due to wrong indentation (issue 225)
* Added an example to show live network traffic (issue 227)
* Added an example demonstrating different output encodings (issue 186)
2011-06-21: Version 1.2.0 "Birds of Paradise"
Version 1.2.0 is a major update. It introduces a whole set of new API.
Bug fixes
* Fixed rendering a very large web page (issue 54)
* Fixed reporting of CoffeeScript compile error (issue 125)
New features
* Added callback for console message (issue 12)
* Improved security model via WebPage object (issue 41)
* Added support for POST, HEAD, PUT, and DELETE (issue 88)
* Scripts filename is now passed as phantom.scriptName
* Added callback to capture resource requests and responses (issue 2)
* Added the ability to load external JavaScript (issue 32)
Examples
* Ported examples to use WebPage object
* Added a new example to upload an image to imagebin.org
* Added a new example to show HTTP POST feature
* Added a new example to sniff network traffic and save it in HAR format
2011-04-27: Version 1.1.0 "Cherry Blossom"
Fixed the script loading to use UTF-8 encoding (Yasuhiro Matsumoto).
Added check for system proxy setting (Yasuhiro Matsumoto).
Fixed building with Cygwin and Qt 4.5 (John Dalton).
Added a new example: driver for QUnit tests (Łukasz Korecki).
Fixed issue #20: problem with JPG transparent color (Alessandro Portale).
Fixed issue #9: ignore first line starting with #! (Matthias, aka fourplusone).
Fixed issue #7: support for file upload for form submission (Matthias, aka fourplusone).
Fixed issue #35: support for disabling images loading (Ariya Hidayat).
Fixed issue #14: enable or disable plugins (Ariya Hidayat).
Added a new example: using Canvas to produce the color wheel (Ariya Hidayat).
Added support for rasterizing as GIF image (Ariya Hidayat).
Added support for CoffeeScript (Ariya Hidayat).
Fixed issue #19: option for setting the proxy (Clint Berry, Ariya Hidayat).
Python implementation using PyQt (James Roe).
Fixed issue #17: Specify paper size for PDF export (Alessandro Portale).
Fixed issue #60: Win32 and OS/2 icon files (Salvador Parra Camacho).
Added clipping rectangle to the render function (Wouter de Bie).
Added an example on sychronous waiting (Gabor Torok).
Added command line option to use disk cache (Jon Turner).
Added text extracting example (Weston Ruter).
Fixed issue #93: Build with Qt < 4.7 (Ariya Hidayat).
Ported all examples to CoffeeScript (Robert Gieseke).
2011-01-17: Version 1.0.0
Initial launch.
The API is centralized at the 'phantom' object (as child of
window object) which has the properties: args, content,
loadStatus, state, userAgent, version, viewportSize, and
the following functions: exit, open, render, sleep.
Several examples are included, among others: web page rasterizer,
weather service, headless test framework driver, and many others.
@@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,45 @@
# [PhantomJS](http://phantomjs.org) - Scriptable Headless WebKit
PhantomJS ([www.phantomjs.org](http://phantomjs.org)) is a headless WebKit scriptable with JavaScript or CoffeeScript. It is used by hundreds of [developers](https://github.com/ariya/phantomjs/wiki/Buzz) and dozens of [organizations](https://github.com/ariya/phantomjs/wiki/Users) for web-related development workflow.
The latest [stable release](http://phantomjs.org/release-1.9.html) is version 1.9 (codenamed <a href="http://phantomjs.org/release-names.html">"Sakura"</a>). Follow the official Twitter stream [@PhantomJS](http://twitter.com/PhantomJS) to get the frequent development updates.
**Note**: Please **do not** create a GitHub pull request **without** reading the [Contribution Guide](https://github.com/ariya/phantomjs/blob/master/CONTRIBUTING.md) first. Failure to do so may result in the rejection of the pull request.
## Use Cases
- **Headless web testing**. Lightning-fast testing without the browser is now possible! Various [test frameworks](https://github.com/ariya/phantomjs/wiki/Headless-Testing) such as Jasmine, Capybara, QUnit, Mocha, WebDriver, YUI Test, BusterJS, FuncUnit, Robot Framework, and many others are supported.
- **Page automation**. [Access and manipulate](https://github.com/ariya/phantomjs/wiki/Page-Automation) web pages with the standard DOM API, or with usual libraries like jQuery.
- **Screen capture**. Programmatically [capture web contents](https://github.com/ariya/phantomjs/wiki/Screen-Capture), including CSs, SVG and Canvas. Build server-side web graphics apps, from a screenshot service to a vector chart rasterizer.
- **Network monitoring**. Automate performance analysis, track [page loading](https://github.com/ariya/phantomjs/wiki/Network-Monitoring) and export as standard HAR format.
## Features
- **Multiplatform**, available on major operating systems: Windows, Mac OS X, Linux, other Unices.
- **Fast and native implementation** of web standards: DOM, CSS, JavaScript, Canvas, SVG. No emulation!
- **Pure headless (no X11) on Linux**, ideal for continuous integration systems. Also runs on Amazon EC2, Heroku, Iron.io.
- **Easy to install**: [Download](http://phantomjs.org/download.html), unpack, and start having fun in just 5 minutes.
## Ecosystem
PhantomJS needs not be used only as a stand-alone tool. Check also some excellent related projects:
- [CasperJS](http://casperjs.org) enables easy navigation scripting and common high-level testing.
- [Poltergeist](https://github.com/jonleighton/poltergeist) allows running Capybara tests headlessly.
- [Guard::Jasmine](https://github.com/netzpirat/guard-jasmine) automatically tests Jasmine specs on Rails when files are modified.
- [GhostDriver](http://github.com/detro/ghostdriver/) complements Selenium tests with a PhantomJS WebDriver implementation.
- [PhantomRobot](https://github.com/datakurre/phantomrobot) runs Robot Framework acceptance tests in the background via PhantomJS.
- [Mocha-PhantomJS](https://github.com/metaskills/mocha-phantomjs) run Mocha tests using PhantomJS.
and many others [related projects](https://github.com/ariya/phantomjs/wiki/Related-Projects).
## Questions?
- Explore the complete [documentation](https://github.com/ariya/phantomjs/wiki)
- Read tons of [user articles](https://github.com/ariya/phantomjs/wiki/Buzz) on using PhantomJS.
- Join the [mailing-list](http://groups.google.com/group/phantomjs) and discuss with other PhantomJS fans.
PhantomJS is free software/open source, and is distributed under the [BSD license](http://opensource.org/licenses/BSD-3-Clause). It contains third-party code, see the included `third-party.txt` file for the license information on third-party code.
PhantomJS is created and maintained by [Ariya Hidayat](http://ariya.ofilabs.com/about) (Twitter: [@ariyahidayat](http://twitter.com/ariyahidayat)), with the help of [many contributors](https://github.com/ariya/phantomjs/contributors).
@@ -0,0 +1,7 @@
system = require 'system'
if system.args.length is 1
console.log 'Try to pass some args when invoking this script!'
else
for arg, i in system.args
console.log i + ': ' + arg
phantom.exit()
@@ -0,0 +1,9 @@
var system = require('system');
if (system.args.length === 1) {
console.log('Try to pass some args when invoking this script!');
} else {
system.args.forEach(function (arg, i) {
console.log(i + ': ' + arg);
});
}
phantom.exit();
@@ -0,0 +1,20 @@
{spawn, execFile} = require "child_process"
child = spawn "ls", ["-lF", "/rooot"]
child.stdout.on "data", (data) ->
console.log "spawnSTDOUT:", JSON.stringify data
child.stderr.on "data", (data) ->
console.log "spawnSTDERR:", JSON.stringify data
child.on "exit", (code) ->
console.log "spawnEXIT:", code
#child.kill "SIGKILL"
execFile "ls", ["-lF", "/usr"], null, (err, stdout, stderr) ->
console.log "execFileSTDOUT:", JSON.stringify stdout
console.log "execFileSTDERR:", JSON.stringify stderr
setTimeout (-> phantom.exit 0), 2000
@@ -0,0 +1,27 @@
var spawn = require("child_process").spawn
var execFile = require("child_process").execFile
var child = spawn("ls", ["-lF", "/rooot"])
child.stdout.on("data", function (data) {
console.log("spawnSTDOUT:", JSON.stringify(data))
})
child.stderr.on("data", function (data) {
console.log("spawnSTDERR:", JSON.stringify(data))
})
child.on("exit", function (code) {
console.log("spawnEXIT:", code)
})
//child.kill("SIGKILL")
execFile("ls", ["-lF", "/usr"], null, function (err, stdout, stderr) {
console.log("execFileSTDOUT:", JSON.stringify(stdout))
console.log("execFileSTDERR:", JSON.stringify(stderr))
})
setTimeout(function () {
phantom.exit(0)
}, 2000)
@@ -0,0 +1,46 @@
page = require('webpage').create()
page.viewportSize = { width: 400, height : 400 }
page.content = '<html><body><canvas id="surface"></canvas></body></html>'
page.evaluate ->
el = document.getElementById 'surface'
context = el.getContext '2d'
width = window.innerWidth
height = window.innerHeight
cx = width / 2
cy = height / 2
radius = width / 2.3
i = 0
el.width = width
el.height = height
imageData = context.createImageData(width, height)
pixels = imageData.data
for y in [0...height]
for x in [0...width]
i = i + 4
rx = x - cx
ry = y - cy
d = rx * rx + ry * ry
if d < radius * radius
hue = 6 * (Math.atan2(ry, rx) + Math.PI) / (2 * Math.PI)
sat = Math.sqrt(d) / radius
g = Math.floor(hue)
f = hue - g
u = 255 * (1 - sat)
v = 255 * (1 - sat * f)
w = 255 * (1 - sat * (1 - f))
pixels[i] = [255, v, u, u, w, 255, 255][g]
pixels[i + 1] = [w, 255, 255, v, u, u, w][g]
pixels[i + 2] = [u, u, w, 255, 255, v, u][g]
pixels[i + 3] = 255
context.putImageData imageData, 0, 0
document.body.style.backgroundColor = 'white'
document.body.style.margin = '0px'
page.render('colorwheel.png')
phantom.exit()
@@ -0,0 +1,51 @@
var page = require('webpage').create();
page.viewportSize = { width: 400, height : 400 };
page.content = '<html><body><canvas id="surface"></canvas></body></html>';
page.evaluate(function() {
var el = document.getElementById('surface'),
context = el.getContext('2d'),
width = window.innerWidth,
height = window.innerHeight,
cx = width / 2,
cy = height / 2,
radius = width / 2.3,
imageData,
pixels,
hue, sat, value,
i = 0, x, y, rx, ry, d,
f, g, p, u, v, w, rgb;
el.width = width;
el.height = height;
imageData = context.createImageData(width, height);
pixels = imageData.data;
for (y = 0; y < height; y = y + 1) {
for (x = 0; x < width; x = x + 1, i = i + 4) {
rx = x - cx;
ry = y - cy;
d = rx * rx + ry * ry;
if (d < radius * radius) {
hue = 6 * (Math.atan2(ry, rx) + Math.PI) / (2 * Math.PI);
sat = Math.sqrt(d) / radius;
g = Math.floor(hue);
f = hue - g;
u = 255 * (1 - sat);
v = 255 * (1 - sat * f);
w = 255 * (1 - sat * (1 - f));
pixels[i] = [255, v, u, u, w, 255, 255][g];
pixels[i + 1] = [w, 255, 255, v, u, u, w][g];
pixels[i + 2] = [u, u, w, 255, 255, v, u][g];
pixels[i + 3] = 255;
}
}
}
context.putImageData(imageData, 0, 0);
document.body.style.backgroundColor = 'white';
document.body.style.margin = '0px';
});
page.render('colorwheel.png');
phantom.exit();
@@ -0,0 +1,8 @@
t = 10
interval = setInterval ->
if t > 0
console.log t--
else
console.log 'BLAST OFF!'
phantom.exit()
, 1000
@@ -0,0 +1,9 @@
var t = 10,
interval = setInterval(function(){
if ( t > 0 ) {
console.log(t--);
} else {
console.log("BLAST OFF!");
phantom.exit();
}
}, 1000);
@@ -0,0 +1,42 @@
page = require('webpage').create()
system = require 'system'
page.onInitialized = ->
page.evaluate ->
userAgent = window.navigator.userAgent
platform = window.navigator.platform
window.navigator =
appCodeName: 'Mozilla'
appName: 'Netscape'
cookieEnabled: false
sniffed: false
window.navigator.__defineGetter__ 'userAgent', ->
window.navigator.sniffed = true
userAgent
window.navigator.__defineGetter__ 'platform', ->
window.navigator.sniffed = true
platform
if system.args.length is 1
console.log 'Usage: detectsniff.coffee <some URL>'
phantom.exit 1
else
address = system.args[1]
console.log 'Checking ' + address + '...'
page.open address, (status) ->
if status isnt 'success'
console.log 'FAIL to load the address'
phantom.exit()
else
window.setTimeout ->
sniffed = page.evaluate(->
navigator.sniffed
)
if sniffed
console.log 'The page tried to sniff the user agent.'
else
console.log 'The page did not try to sniff the user agent.'
phantom.exit()
, 1500
@@ -0,0 +1,59 @@
// Detect if a web page sniffs the user agent or not.
var page = require('webpage').create(),
system = require('system'),
sniffed,
address;
page.onInitialized = function () {
page.evaluate(function () {
(function () {
var userAgent = window.navigator.userAgent,
platform = window.navigator.platform;
window.navigator = {
appCodeName: 'Mozilla',
appName: 'Netscape',
cookieEnabled: false,
sniffed: false
};
window.navigator.__defineGetter__('userAgent', function () {
window.navigator.sniffed = true;
return userAgent;
});
window.navigator.__defineGetter__('platform', function () {
window.navigator.sniffed = true;
return platform;
});
})();
});
};
if (system.args.length === 1) {
console.log('Usage: detectsniff.js <some URL>');
phantom.exit(1);
} else {
address = system.args[1];
console.log('Checking ' + address + '...');
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
phantom.exit();
} else {
window.setTimeout(function () {
sniffed = page.evaluate(function () {
return navigator.sniffed;
});
if (sniffed) {
console.log('The page tried to sniff the user agent.');
} else {
console.log('The page did not try to sniff the user agent.');
}
phantom.exit();
}, 1500);
}
});
}
@@ -0,0 +1,30 @@
# Get driving direction using Google Directions API.
page = require('webpage').create()
system = require 'system'
if system.args.length < 3
console.log 'Usage: direction.coffee origin destination'
console.log 'Example: direction.coffee "San Diego" "Palo Alto"'
phantom.exit 1
else
origin = system.args[1]
dest = system.args[2]
page.open encodeURI('http://maps.googleapis.com/maps/api/directions/xml?origin=' + origin +
'&destination=' + dest + '&units=imperial&mode=driving&sensor=false'),
(status) ->
if status isnt 'success'
console.log 'Unable to access network'
else
steps = page.content.match(/<html_instructions>(.*)<\/html_instructions>/ig)
if not steps
console.log 'No data available for ' + origin + ' to ' + dest
else
for ins in steps
ins = ins.replace(/\&lt;/ig, '<').replace(/\&gt;/ig, '>')
ins = ins.replace(/\<div/ig, '\n<div')
ins = ins.replace(/<.*?>/g, '')
console.log(ins)
console.log ''
console.log page.content.match(/<copyrights>.*<\/copyrights>/ig).join('').replace(/<.*?>/g, '')
phantom.exit()
@@ -0,0 +1,35 @@
// Get driving direction using Google Directions API.
var page = require('webpage').create(),
system = require('system'),
origin, dest, steps;
if (system.args.length < 3) {
console.log('Usage: direction.js origin destination');
console.log('Example: direction.js "San Diego" "Palo Alto"');
phantom.exit(1);
} else {
origin = system.args[1];
dest = system.args[2];
page.open(encodeURI('http://maps.googleapis.com/maps/api/directions/xml?origin=' + origin +
'&destination=' + dest + '&units=imperial&mode=driving&sensor=false'), function (status) {
if (status !== 'success') {
console.log('Unable to access network');
} else {
steps = page.content.match(/<html_instructions>(.*)<\/html_instructions>/ig);
if (steps == null) {
console.log('No data available for ' + origin + ' to ' + dest);
} else {
steps.forEach(function (ins) {
ins = ins.replace(/\&lt;/ig, '<').replace(/\&gt;/ig, '>');
ins = ins.replace(/\<div/ig, '\n<div');
ins = ins.replace(/<.*?>/g, '');
console.log(ins);
});
console.log('');
console.log(page.content.match(/<copyrights>.*<\/copyrights>/ig).join('').replace(/<.*?>/g, ''));
}
}
phantom.exit();
});
}
@@ -0,0 +1,19 @@
# echoToFile.coffee - Write in a given file all the parameters passed on the CLI
fs = require 'fs'
system = require 'system'
if system.args.length < 3
console.log "Usage: echoToFile.coffee DESTINATION_FILE <arguments to echo...>"
phantom.exit 1
else
content = ""
f = null
i = 2
while i < system.args.length
content += system.args[i] + (if i == system.args.length - 1 then "" else " ")
++i
try
fs.write system.args[1], content, "w"
catch e
console.log e
phantom.exit()
@@ -0,0 +1,23 @@
// echoToFile.js - Write in a given file all the parameters passed on the CLI
var fs = require('fs'),
system = require('system');
if (system.args.length < 3) {
console.log("Usage: echoToFile.js DESTINATION_FILE <arguments to echo...>");
phantom.exit(1);
} else {
var content = '',
f = null,
i;
for ( i= 2; i < system.args.length; ++i ) {
content += system.args[i] + (i === system.args.length-1 ? '' : ' ');
}
try {
fs.write(system.args[1], content, 'w');
} catch(e) {
console.log(e);
}
phantom.exit();
}
@@ -0,0 +1,23 @@
feature = undefined
supported = []
unsupported = []
phantom.injectJs "modernizr.js"
console.log "Detected features (using Modernizr " + Modernizr._version + "):"
for feature of Modernizr
if Modernizr.hasOwnProperty(feature)
if feature[0] isnt "_" and typeof Modernizr[feature] isnt "function" and feature isnt "input" and feature isnt "inputtypes"
if Modernizr[feature]
supported.push feature
else
unsupported.push feature
console.log ""
console.log "Supported:"
supported.forEach (e) ->
console.log " " + e
console.log ""
console.log "Not supported:"
unsupported.forEach (e) ->
console.log " " + e
phantom.exit()
@@ -0,0 +1,30 @@
var feature, supported = [], unsupported = [];
phantom.injectJs('modernizr.js');
console.log('Detected features (using Modernizr ' + Modernizr._version + '):');
for (feature in Modernizr) {
if (Modernizr.hasOwnProperty(feature)) {
if (feature[0] !== '_' && typeof Modernizr[feature] !== 'function' &&
feature !== 'input' && feature !== 'inputtypes') {
if (Modernizr[feature]) {
supported.push(feature);
} else {
unsupported.push(feature);
}
}
}
}
console.log('');
console.log('Supported:');
supported.forEach(function (e) {
console.log(' ' + e);
});
console.log('');
console.log('Not supported:');
unsupported.forEach(function (e) {
console.log(' ' + e);
});
phantom.exit();
@@ -0,0 +1,8 @@
fibs = [0, 1]
f = ->
console.log fibs[fibs.length - 1]
fibs.push fibs[fibs.length - 1] + fibs[fibs.length - 2]
if fibs.length > 10
window.clearInterval ticker
phantom.exit()
ticker = window.setInterval(f, 300)
@@ -0,0 +1,9 @@
var fibs = [0, 1];
var ticker = window.setInterval(function () {
console.log(fibs[fibs.length - 1]);
fibs.push(fibs[fibs.length - 1] + fibs[fibs.length - 2]);
if (fibs.length > 10) {
window.clearInterval(ticker);
phantom.exit();
}
}, 300);
@@ -0,0 +1,33 @@
# List following and followers from several accounts
users = [
'PhantomJS'
'ariyahidayat'
'detronizator'
'KDABQt'
'lfranchi'
'jonleighton'
'_jamesmgreene'
'Vitalliumm'
]
follow = (user, callback) ->
page = require('webpage').create()
page.open 'http://mobile.twitter.com/' + user, (status) ->
if status is 'fail'
console.log user + ': ?'
else
data = page.evaluate -> document.querySelector('div.profile td.stat.stat-last div.statnum').innerText;
console.log user + ': ' + data
page.close()
callback.apply()
process = () ->
if (users.length > 0)
user = users[0]
users.splice(0, 1)
follow(user, process)
else
phantom.exit()
process()
@@ -0,0 +1,38 @@
// List following and followers from several accounts
var users = ['PhantomJS',
'ariyahidayat',
'detronizator',
'KDABQt',
'lfranchi',
'jonleighton',
'_jamesmgreene',
'Vitalliumm'];
function follow(user, callback) {
var page = require('webpage').create();
page.open('http://mobile.twitter.com/' + user, function (status) {
if (status === 'fail') {
console.log(user + ': ?');
} else {
var data = page.evaluate(function () {
return document.querySelector('div.profile td.stat.stat-last div.statnum').innerText;
});
console.log(user + ': ' + data);
}
page.close();
callback.apply();
});
}
function process() {
if (users.length > 0) {
var user = users[0];
users.splice(0, 1);
follow(user, process);
} else {
phantom.exit();
}
}
process();
@@ -0,0 +1,2 @@
console.log 'Hello, world!'
phantom.exit()
@@ -0,0 +1,2 @@
console.log('Hello, world!');
phantom.exit();
@@ -0,0 +1,20 @@
# Upload an image to imagebin.org
page = require('webpage').create()
system = require 'system'
if system.args.length isnt 2
console.log 'Usage: imagebin.coffee filename'
phantom.exit 1
else
fname = system.args[1]
page.open 'http://imagebin.org/index.php?page=add', ->
page.uploadFile 'input[name=image]', fname
page.evaluate ->
document.querySelector('input[name=nickname]').value = 'phantom'
document.querySelector('input[name=disclaimer_agree]').click()
document.querySelector('form').submit()
window.setTimeout ->
phantom.exit()
, 3000
@@ -0,0 +1,23 @@
// Upload an image to imagebin.org
var page = require('webpage').create(),
system = require('system'),
fname;
if (system.args.length !== 2) {
console.log('Usage: imagebin.js filename');
phantom.exit(1);
} else {
fname = system.args[1];
page.open("http://imagebin.org/index.php?page=add", function () {
page.uploadFile('input[name=image]', fname);
page.evaluate(function () {
document.querySelector('input[name=nickname]').value = 'phantom';
document.querySelector('input[name=disclaimer_agree]').click()
document.querySelector('form').submit();
});
window.setTimeout(function () {
phantom.exit();
}, 3000);
});
}
@@ -0,0 +1,23 @@
# Use 'page.injectJs()' to load the script itself in the Page context
if phantom?
page = require('webpage').create()
# Route "console.log()" calls from within the Page context to the main
# Phantom context (i.e. current "this")
page.onConsoleMessage = (msg) -> console.log(msg)
page.onAlert = (msg) -> console.log(msg)
console.log "* Script running in the Phantom context."
console.log "* Script will 'inject' itself in a page..."
page.open "about:blank", (status) ->
if status is "success"
if page.injectJs("injectme.coffee")
console.log "... done injecting itself!"
else
console.log "... fail! Check the $PWD?!"
phantom.exit()
else
alert "* Script running in the Page context."
@@ -0,0 +1,25 @@
// Use 'page.injectJs()' to load the script itself in the Page context
if ( typeof(phantom) !== "undefined" ) {
var page = require('webpage').create();
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.onAlert = function(msg) {
console.log(msg);
};
console.log("* Script running in the Phantom context.");
console.log("* Script will 'inject' itself in a page...");
page.open("about:blank", function(status) {
if ( status === "success" ) {
console.log(page.injectJs("injectme.js") ? "... done injecting itself!" : "... fail! Check the $PWD?!");
}
phantom.exit();
});
} else {
alert("* Script running in the Page context.");
}
@@ -0,0 +1,13 @@
# Give the estimated location based on the IP address.
window.cb = (data) ->
loc = data.city
if data.region_name.length > 0
loc = loc + ', ' + data.region_name
console.log 'IP address: ' + data.ip
console.log 'Estimated location: ' + loc
phantom.exit()
el = document.createElement 'script'
el.src = 'http://freegeoip.net/json/?callback=window.cb'
document.body.appendChild el
@@ -0,0 +1,14 @@
// Give the estimated location based on the IP address.
cb = function (data) {
var loc = data.city;
if (data.region_name.length > 0)
loc = loc + ', ' + data.region_name;
console.log('IP address: ' + data.ip);
console.log('Estimated location: ' + loc);
phantom.exit();
};
var el = document.createElement('script');
el.src = 'http://freegeoip.net/json/?callback=cb';
document.body.appendChild(el);
@@ -0,0 +1,18 @@
page = require('webpage').create()
system = require 'system'
if system.args.length is 1
console.log 'Usage: loadspeed.coffee <some URL>'
phantom.exit 1
else
t = Date.now()
address = system.args[1]
page.open address, (status) ->
if status isnt 'success'
console.log('FAIL to load the address')
else
t = Date.now() - t
console.log('Page title is ' + page.evaluate( (-> document.title) ))
console.log('Loading time ' + t + ' msec')
phantom.exit()
@@ -0,0 +1,23 @@
var page = require('webpage').create(),
system = require('system'),
t, address;
if (system.args.length === 1) {
console.log('Usage: loadspeed.js <some URL>');
phantom.exit(1);
} else {
t = Date.now();
address = system.args[1];
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
} else {
t = Date.now() - t;
console.log('Page title is ' + page.evaluate(function () {
return document.title;
}));
console.log('Loading time ' + t + ' msec');
}
phantom.exit();
});
}
@@ -0,0 +1,20 @@
page = require("webpage").create()
system = require("system")
if system.args.length < 2
console.log "Usage: loadurlwithoutcss.js URL"
phantom.exit()
address = system.args[1]
page.onResourceRequested = (requestData, request) ->
if (/http:\/\/.+?\.css/g).test(requestData["url"]) or requestData["Content-Type"] is "text/css"
console.log "The url of the request is matching. Aborting: " + requestData["url"]
request.abort()
page.open address, (status) ->
if status is "success"
phantom.exit()
else
console.log "Unable to load the address!"
phantom.exit()
@@ -0,0 +1,25 @@
var page = require('webpage').create(),
system = require('system');
if (system.args.length < 2) {
console.log('Usage: loadurlwithoutcss.js URL');
phantom.exit();
}
var address = system.args[1];
page.onResourceRequested = function(requestData, request) {
if ((/http:\/\/.+?\.css/gi).test(requestData['url']) || requestData['Content-Type'] == 'text/css') {
console.log('The url of the request is matching. Aborting: ' + requestData['url']);
request.abort();
}
};
page.open(address, function(status) {
if (status === 'success') {
phantom.exit();
} else {
console.log('Unable to load the address!');
phantom.exit();
}
});
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,4 @@
universe = require './universe'
universe.start()
console.log 'The answer is' + universe.answer
phantom.exit()
@@ -0,0 +1,4 @@
var universe = require('./universe');
universe.start();
console.log('The answer is' + universe.answer);
phantom.exit();
@@ -0,0 +1,13 @@
# List movies from kids-in-mind.com
window.cbfunc = (data) ->
globaldata = data
list = data.query.results.movie
for item in list
console.log item.title + ' [' + item.rating.MPAA.content + ']'
phantom.exit()
el = document.createElement 'script'
el.src =
"http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20movies.kids-in-mind&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=window.cbfunc"
document.body.appendChild el
@@ -0,0 +1,14 @@
// List movies from kids-in-mind.com
var cbfunc = function (data) {
globaldata= data;
var list = data.query.results.movie;
list.forEach(function (item) {
console.log(item.title + ' [' + item.rating.MPAA.content + ']');
});
phantom.exit();
};
var el = document.createElement('script');
el.src = 'http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20movies.kids-in-mind&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=cbfunc';
document.body.appendChild(el);
@@ -0,0 +1,18 @@
page = require('webpage').create()
system = require 'system'
if system.args.length is 1
console.log 'Usage: netlog.coffee <some URL>'
phantom.exit 1
else
address = system.args[1]
page.onResourceRequested = (req) ->
console.log 'requested ' + JSON.stringify(req, undefined, 4)
page.onResourceReceived = (res) ->
console.log 'received ' + JSON.stringify(res, undefined, 4)
page.open address, (status) ->
if status isnt 'success'
console.log 'FAIL to load the address'
phantom.exit()
@@ -0,0 +1,25 @@
var page = require('webpage').create(),
system = require('system'),
address;
if (system.args.length === 1) {
console.log('Usage: netlog.js <some URL>');
phantom.exit(1);
} else {
address = system.args[1];
page.onResourceRequested = function (req) {
console.log('requested: ' + JSON.stringify(req, undefined, 4));
};
page.onResourceReceived = function (res) {
console.log('received: ' + JSON.stringify(res, undefined, 4));
};
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
}
phantom.exit();
});
}
@@ -0,0 +1,114 @@
if not Date::toISOString
Date::toISOString = ->
pad = (n) ->
if n < 10 then '0' + n else n
ms = (n) ->
if n < 10 then '00' + n else (if n < 100 then '0' + n else n)
@getFullYear() + '-' +
pad(@getMonth() + 1) + '-' +
pad(@getDate()) + 'T' +
pad(@getHours()) + ':' +
pad(@getMinutes()) + ':' +
pad(@getSeconds()) + '.' +
ms(@getMilliseconds()) + 'Z'
createHAR = (address, title, startTime, resources) ->
entries = []
resources.forEach (resource) ->
request = resource.request
startReply = resource.startReply
endReply = resource.endReply
if not request or not startReply or not endReply
return
entries.push
startedDateTime: request.time.toISOString()
time: endReply.time - request.time
request:
method: request.method
url: request.url
httpVersion: 'HTTP/1.1'
cookies: []
headers: request.headers
queryString: []
headersSize: -1
bodySize: -1
response:
status: endReply.status
statusText: endReply.statusText
httpVersion: 'HTTP/1.1'
cookies: []
headers: endReply.headers
redirectURL: ''
headersSize: -1
bodySize: startReply.bodySize
content:
size: startReply.bodySize
mimeType: endReply.contentType
cache: {}
timings:
blocked: 0
dns: -1
connect: -1
send: 0
wait: startReply.time - request.time
receive: endReply.time - startReply.time
ssl: -1
pageref: address
log:
version: '1.2'
creator:
name: 'PhantomJS'
version: phantom.version.major + '.' + phantom.version.minor + '.' + phantom.version.patch
pages: [
startedDateTime: startTime.toISOString()
id: address
title: title
pageTimings:
onLoad: page.endTime - page.startTime
]
entries: entries
page = require('webpage').create()
system = require 'system'
if system.args.length is 1
console.log 'Usage: netsniff.coffee <some URL>'
phantom.exit 1
else
page.address = system.args[1]
page.resources = []
page.onLoadStarted = ->
page.startTime = new Date()
page.onResourceRequested = (req) ->
page.resources[req.id] =
request: req
startReply: null
endReply: null
page.onResourceReceived = (res) ->
if res.stage is 'start'
page.resources[res.id].startReply = res
if res.stage is 'end'
page.resources[res.id].endReply = res
page.open page.address, (status) ->
if status isnt 'success'
console.log 'FAIL to load the address'
phantom.exit(1)
else
page.endTime = new Date()
page.title = page.evaluate ->
document.title
har = createHAR page.address, page.title, page.startTime, page.resources
console.log JSON.stringify har, undefined, 4
phantom.exit()
@@ -0,0 +1,143 @@
if (!Date.prototype.toISOString) {
Date.prototype.toISOString = function () {
function pad(n) { return n < 10 ? '0' + n : n; }
function ms(n) { return n < 10 ? '00'+ n : n < 100 ? '0' + n : n }
return this.getFullYear() + '-' +
pad(this.getMonth() + 1) + '-' +
pad(this.getDate()) + 'T' +
pad(this.getHours()) + ':' +
pad(this.getMinutes()) + ':' +
pad(this.getSeconds()) + '.' +
ms(this.getMilliseconds()) + 'Z';
}
}
function createHAR(address, title, startTime, resources)
{
var entries = [];
resources.forEach(function (resource) {
var request = resource.request,
startReply = resource.startReply,
endReply = resource.endReply;
if (!request || !startReply || !endReply) {
return;
}
// Exclude Data URI from HAR file because
// they aren't included in specification
if (request.url.match(/(^data:image\/.*)/i)) {
return;
}
entries.push({
startedDateTime: request.time.toISOString(),
time: endReply.time - request.time,
request: {
method: request.method,
url: request.url,
httpVersion: "HTTP/1.1",
cookies: [],
headers: request.headers,
queryString: [],
headersSize: -1,
bodySize: -1
},
response: {
status: endReply.status,
statusText: endReply.statusText,
httpVersion: "HTTP/1.1",
cookies: [],
headers: endReply.headers,
redirectURL: "",
headersSize: -1,
bodySize: startReply.bodySize,
content: {
size: startReply.bodySize,
mimeType: endReply.contentType
}
},
cache: {},
timings: {
blocked: 0,
dns: -1,
connect: -1,
send: 0,
wait: startReply.time - request.time,
receive: endReply.time - startReply.time,
ssl: -1
},
pageref: address
});
});
return {
log: {
version: '1.2',
creator: {
name: "PhantomJS",
version: phantom.version.major + '.' + phantom.version.minor +
'.' + phantom.version.patch
},
pages: [{
startedDateTime: startTime.toISOString(),
id: address,
title: title,
pageTimings: {
onLoad: page.endTime - page.startTime
}
}],
entries: entries
}
};
}
var page = require('webpage').create(),
system = require('system');
if (system.args.length === 1) {
console.log('Usage: netsniff.js <some URL>');
phantom.exit(1);
} else {
page.address = system.args[1];
page.resources = [];
page.onLoadStarted = function () {
page.startTime = new Date();
};
page.onResourceRequested = function (req) {
page.resources[req.id] = {
request: req,
startReply: null,
endReply: null
};
};
page.onResourceReceived = function (res) {
if (res.stage === 'start') {
page.resources[res.id].startReply = res;
}
if (res.stage === 'end') {
page.resources[res.id].endReply = res;
}
};
page.open(page.address, function (status) {
var har;
if (status !== 'success') {
console.log('FAIL to load the address');
phantom.exit(1);
} else {
page.endTime = new Date();
page.title = page.evaluate(function () {
return document.title;
});
har = createHAR(page.address, page.title, page.startTime, page.resources);
console.log(JSON.stringify(har, undefined, 4));
phantom.exit();
}
});
}
@@ -0,0 +1,12 @@
helloWorld = () -> console.log phantom.outputEncoding + ": こんにちは、世界!"
console.log "Using default encoding..."
helloWorld()
console.log "\nUsing other encodings..."
for enc in ["euc-jp", "sjis", "utf8", "System"]
do (enc) ->
phantom.outputEncoding = enc
helloWorld()
phantom.exit()
@@ -0,0 +1,16 @@
function helloWorld() {
console.log(phantom.outputEncoding + ": こんにちは、世界!");
}
console.log("Using default encoding...");
helloWorld();
console.log("\nUsing other encodings...");
var encodings = ["euc-jp", "sjis", "utf8", "System"];
for (var i = 0; i < encodings.length; i++) {
phantom.outputEncoding = encodings[i];
helloWorld();
}
phantom.exit()
@@ -0,0 +1,132 @@
# The purpose of this is to show how and when events fire, considering 5 steps
# happening as follows:
#
# 1. Load URL
# 2. Load same URL, but adding an internal FRAGMENT to it
# 3. Click on an internal Link, that points to another internal FRAGMENT
# 4. Click on an external Link, that will send the page somewhere else
# 5. Close page
#
# Take particular care when going through the output, to understand when
# things happen (and in which order). Particularly, notice what DOESN'T
# happen during step 3.
#
# If invoked with "-v" it will print out the Page Resources as they are
# Requested and Received.
#
# NOTE.1: The "onConsoleMessage/onAlert/onPrompt/onConfirm" events are
# registered but not used here. This is left for you to have fun with.
# NOTE.2: This script is not here to teach you ANY JavaScript. It's aweful!
# NOTE.3: Main audience for this are people new to PhantomJS.
printArgs = ->
i = undefined
ilen = undefined
i = 0
ilen = arguments_.length
while i < ilen
console.log " arguments[" + i + "] = " + JSON.stringify(arguments_[i])
++i
console.log ""
sys = require("system")
page = require("webpage").create()
logResources = false
step1url = "http://en.wikipedia.org/wiki/DOM_events"
step2url = "http://en.wikipedia.org/wiki/DOM_events#Event_flow"
logResources = true if sys.args.length > 1 and sys.args[1] is "-v"
#//////////////////////////////////////////////////////////////////////////////
page.onInitialized = ->
console.log "page.onInitialized"
printArgs.apply this, arguments_
page.onLoadStarted = ->
console.log "page.onLoadStarted"
printArgs.apply this, arguments_
page.onLoadFinished = ->
console.log "page.onLoadFinished"
printArgs.apply this, arguments_
page.onUrlChanged = ->
console.log "page.onUrlChanged"
printArgs.apply this, arguments_
page.onNavigationRequested = ->
console.log "page.onNavigationRequested"
printArgs.apply this, arguments_
if logResources is true
page.onResourceRequested = ->
console.log "page.onResourceRequested"
printArgs.apply this, arguments_
page.onResourceReceived = ->
console.log "page.onResourceReceived"
printArgs.apply this, arguments_
page.onClosing = ->
console.log "page.onClosing"
printArgs.apply this, arguments_
# window.console.log(msg);
page.onConsoleMessage = ->
console.log "page.onConsoleMessage"
printArgs.apply this, arguments_
# window.alert(msg);
page.onAlert = ->
console.log "page.onAlert"
printArgs.apply this, arguments_
# var confirmed = window.confirm(msg);
page.onConfirm = ->
console.log "page.onConfirm"
printArgs.apply this, arguments_
# var user_value = window.prompt(msg, default_value);
page.onPrompt = ->
console.log "page.onPrompt"
printArgs.apply this, arguments_
#//////////////////////////////////////////////////////////////////////////////
setTimeout (->
console.log ""
console.log "### STEP 1: Load '" + step1url + "'"
page.open step1url
), 0
setTimeout (->
console.log ""
console.log "### STEP 2: Load '" + step2url + "' (load same URL plus FRAGMENT)"
page.open step2url
), 5000
setTimeout (->
console.log ""
console.log "### STEP 3: Click on page internal link (aka FRAGMENT)"
page.evaluate ->
ev = document.createEvent("MouseEvents")
ev.initEvent "click", true, true
document.querySelector("a[href='#Event_object']").dispatchEvent ev
), 10000
setTimeout (->
console.log ""
console.log "### STEP 4: Click on page external link"
page.evaluate ->
ev = document.createEvent("MouseEvents")
ev.initEvent "click", true, true
document.querySelector("a[title='JavaScript']").dispatchEvent ev
), 15000
setTimeout (->
console.log ""
console.log "### STEP 5: Close page and shutdown (with a delay)"
page.close()
setTimeout (->
phantom.exit()
), 100
), 20000
@@ -0,0 +1,142 @@
// The purpose of this is to show how and when events fire, considering 5 steps
// happening as follows:
//
// 1. Load URL
// 2. Load same URL, but adding an internal FRAGMENT to it
// 3. Click on an internal Link, that points to another internal FRAGMENT
// 4. Click on an external Link, that will send the page somewhere else
// 5. Close page
//
// Take particular care when going through the output, to understand when
// things happen (and in which order). Particularly, notice what DOESN'T
// happen during step 3.
//
// If invoked with "-v" it will print out the Page Resources as they are
// Requested and Received.
//
// NOTE.1: The "onConsoleMessage/onAlert/onPrompt/onConfirm" events are
// registered but not used here. This is left for you to have fun with.
// NOTE.2: This script is not here to teach you ANY JavaScript. It's aweful!
// NOTE.3: Main audience for this are people new to PhantomJS.
var sys = require("system"),
page = require("webpage").create(),
logResources = false,
step1url = "http://en.wikipedia.org/wiki/DOM_events",
step2url = "http://en.wikipedia.org/wiki/DOM_events#Event_flow";
if (sys.args.length > 1 && sys.args[1] === "-v") {
logResources = true;
}
function printArgs() {
var i, ilen;
for (i = 0, ilen = arguments.length; i < ilen; ++i) {
console.log(" arguments[" + i + "] = " + JSON.stringify(arguments[i]));
}
console.log("");
}
////////////////////////////////////////////////////////////////////////////////
page.onInitialized = function() {
console.log("page.onInitialized");
printArgs.apply(this, arguments);
};
page.onLoadStarted = function() {
console.log("page.onLoadStarted");
printArgs.apply(this, arguments);
};
page.onLoadFinished = function() {
console.log("page.onLoadFinished");
printArgs.apply(this, arguments);
};
page.onUrlChanged = function() {
console.log("page.onUrlChanged");
printArgs.apply(this, arguments);
};
page.onNavigationRequested = function() {
console.log("page.onNavigationRequested");
printArgs.apply(this, arguments);
};
if (logResources === true) {
page.onResourceRequested = function() {
console.log("page.onResourceRequested");
printArgs.apply(this, arguments);
};
page.onResourceReceived = function() {
console.log("page.onResourceReceived");
printArgs.apply(this, arguments);
};
}
page.onClosing = function() {
console.log("page.onClosing");
printArgs.apply(this, arguments);
};
// window.console.log(msg);
page.onConsoleMessage = function() {
console.log("page.onConsoleMessage");
printArgs.apply(this, arguments);
};
// window.alert(msg);
page.onAlert = function() {
console.log("page.onAlert");
printArgs.apply(this, arguments);
};
// var confirmed = window.confirm(msg);
page.onConfirm = function() {
console.log("page.onConfirm");
printArgs.apply(this, arguments);
};
// var user_value = window.prompt(msg, default_value);
page.onPrompt = function() {
console.log("page.onPrompt");
printArgs.apply(this, arguments);
};
////////////////////////////////////////////////////////////////////////////////
setTimeout(function() {
console.log("");
console.log("### STEP 1: Load '" + step1url + "'");
page.open(step1url);
}, 0);
setTimeout(function() {
console.log("");
console.log("### STEP 2: Load '" + step2url + "' (load same URL plus FRAGMENT)");
page.open(step2url);
}, 5000);
setTimeout(function() {
console.log("");
console.log("### STEP 3: Click on page internal link (aka FRAGMENT)");
page.evaluate(function() {
var ev = document.createEvent("MouseEvents");
ev.initEvent("click", true, true);
document.querySelector("a[href='#Event_object']").dispatchEvent(ev);
});
}, 10000);
setTimeout(function() {
console.log("");
console.log("### STEP 4: Click on page external link");
page.evaluate(function() {
var ev = document.createEvent("MouseEvents");
ev.initEvent("click", true, true);
document.querySelector("a[title='JavaScript']").dispatchEvent(ev);
});
}, 15000);
setTimeout(function() {
console.log("");
console.log("### STEP 5: Close page and shutdown (with a delay)");
page.close();
setTimeout(function(){
phantom.exit();
}, 100);
}, 20000);

Some files were not shown because too many files have changed in this diff Show More