Created
March 27, 2014 13:46
-
-
Save maricn/9807908 to your computer and use it in GitHub Desktop.
JavaScript Feedback form (similar to github.com/niklasvh/feedback.js) with back button to get one step back. [feedback.js is used as an example in index.html as if it is in 'js' folder with jquery and feedback.css in 'css' folder with bootstrap]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* Bootstrap v2.0.4 | |
* | |
* Copyright 2012 Twitter, Inc | |
* Licensed under the Apache License v2.0 | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Designed and built with all the love in the world @twitter by @mdo and @fat. | |
*/ | |
.feedback-review label { | |
font-size: 14px; | |
} | |
.feedback-body .feedback-error { | |
color: #b94a48; | |
border-color: #b94a48; | |
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
} | |
.feedback-body .feedback-error:focus { | |
border-color: #953b39; | |
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; | |
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; | |
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; | |
} | |
.feedback-body p a { | |
color: #0088cc; | |
text-decoration: none; | |
} | |
.feedback-body p a:hover { | |
color: #005580; | |
text-decoration: underline; | |
} | |
.feedback-modal h3 { | |
line-height: 27px; | |
font-size: 18px; | |
margin: 0; | |
font-weight: bold; | |
color: #333; | |
text-rendering: optimizelegibility; | |
} | |
.feedback-modal { | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
font-size: 13px; | |
line-height: 18px; | |
color: #333; | |
position: fixed; | |
top: 50%; | |
left: 50%; | |
z-index: 2050; | |
max-height: 500px; | |
overflow: auto; | |
width: 560px; | |
margin: -250px 0 0 -280px; | |
background-color: #ffffff; | |
border: 1px solid #999; | |
border: 1px solid rgba(0, 0, 0, 0.3); | |
*border: 1px solid #999; | |
/* IE6-7 */ | |
-webkit-border-radius: 6px; | |
-moz-border-radius: 6px; | |
border-radius: 6px; | |
-webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); | |
-moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); | |
box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); | |
-webkit-background-clip: padding-box; | |
-moz-background-clip: padding-box; | |
background-clip: padding-box; | |
-webkit-transition: all 2s ease 0s; | |
-moz-transition: all 2s ease 0s; | |
-ms-transition: all 2s ease 0s; | |
-o-transition: all 2s ease 0s; | |
} | |
.feedback-modal .feedback-close { | |
float: right; | |
font-size: 20px; | |
font-weight: bold; | |
line-height: 18px; | |
color: #000000; | |
text-shadow: 0 1px 0 #ffffff; | |
opacity: 0.2; | |
filter: alpha(opacity=20); | |
} | |
.feedback-modal .feedback-close:hover { | |
color: #000000; | |
text-decoration: none; | |
opacity: 0.4; | |
filter: alpha(opacity=40); | |
cursor: pointer; | |
} | |
.feedback-btn { | |
display: inline-block; | |
padding: 4px 10px 4px; | |
margin-bottom: 0; | |
font-size: 13px; | |
line-height: 18px; | |
color: #333333; | |
text-align: center; | |
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); | |
vertical-align: middle; | |
background-color: #f5f5f5; | |
background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); | |
background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); | |
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); | |
background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); | |
background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); | |
background-image: linear-gradient(top, #ffffff, #e6e6e6); | |
background-repeat: repeat-x; | |
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); | |
border-color: #e6e6e6 #e6e6e6 #bfbfbf; | |
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); | |
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); | |
border: 1px solid #ccc; | |
border-bottom-color: #bbb; | |
-webkit-border-radius: 4px; | |
-moz-border-radius: 4px; | |
border-radius: 4px; | |
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); | |
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); | |
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); | |
cursor: pointer; | |
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); | |
*margin-left: .3em; | |
} | |
.feedback-btn:hover, | |
.feedback-btn:active, | |
.feedback-btn.active, | |
.feedback-btn.disabled, | |
.feedback-btn[disabled] { | |
background-color: #e6e6e6; | |
} | |
.feedback-btn:active, .feedback-btn.active { | |
background-color: #cccccc \9; | |
} | |
.feedback-btn:first-child { | |
*margin-left: 0; | |
} | |
.feedback-btn:hover { | |
color: #333333; | |
text-decoration: none; | |
background-color: #e6e6e6; | |
background-position: 0 -15px; | |
-webkit-transition: background-position 0.1s linear; | |
-moz-transition: background-position 0.1s linear; | |
-ms-transition: background-position 0.1s linear; | |
-o-transition: background-position 0.1s linear; | |
transition: background-position 0.1s linear; | |
} | |
.feedback-btn:focus { | |
outline: thin dotted #333; | |
outline: 5px auto -webkit-focus-ring-color; | |
outline-offset: -2px; | |
} | |
.feedback-btn.active, .feedback-btn:active { | |
background-image: none; | |
-webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); | |
-moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); | |
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); | |
background-color: #e6e6e6; | |
background-color: #d9d9d9 \9; | |
outline: 0; | |
} | |
.feedback-btn.disabled, .feedback-btn[disabled] { | |
cursor: default; | |
background-image: none; | |
background-color: #e6e6e6; | |
opacity: 0.65; | |
filter: alpha(opacity=65); | |
-webkit-box-shadow: none; | |
-moz-box-shadow: none; | |
box-shadow: none; | |
} | |
.feedback-btn-small { | |
padding: 5px 9px; | |
font-size: 11px; | |
line-height: 16px; | |
} | |
.feedback-btn-small [class^="icon-"] { | |
margin-top: -1px; | |
} | |
.feedback-btn-inverse, | |
.feedback-btn-inverse:hover { | |
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); | |
color: #ffffff; | |
} | |
.feedback-btn-inverse { | |
background-color: #393939; | |
background-image: -moz-linear-gradient(top, #454545, #262626); | |
background-image: -ms-linear-gradient(top, #454545, #262626); | |
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#454545), to(#262626)); | |
background-image: -webkit-linear-gradient(top, #454545, #262626); | |
background-image: -o-linear-gradient(top, #454545, #262626); | |
background-image: linear-gradient(top, #454545, #262626); | |
background-repeat: repeat-x; | |
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#454545', endColorstr='#262626', GradientType=0); | |
border-color: #262626 #262626 #000000; | |
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); | |
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); | |
} | |
.feedback-btn-inverse:hover, | |
.feedback-btn-inverse:active, | |
.feedback-btn-inverse.active, | |
.feedback-btn-inverse.disabled, | |
.feedback-btn-inverse[disabled] { | |
background-color: #262626; | |
} | |
.feedback-btn-inverse:active, .feedback-btn-inverse.active { | |
background-color: #0c0c0c \9; | |
} | |
button.feedback-btn, input[type="submit"].feedback-btn { | |
*padding-top: 2px; | |
*padding-bottom: 2px; | |
} | |
button.feedback-btn::-moz-focus-inner, input[type="submit"].feedback-btn::-moz-focus-inner { | |
padding: 0; | |
border: 0; | |
} | |
button.feedback-btn.large, input[type="submit"].feedback-btn.large { | |
*padding-top: 7px; | |
*padding-bottom: 7px; | |
} | |
button.feedback-btn.small, input[type="submit"].feedback-btn.small { | |
*padding-top: 3px; | |
*padding-bottom: 3px; | |
} | |
.feedback-btn .caret { | |
margin-top: 7px; | |
margin-left: 0; | |
} | |
.feedback-btn:hover .caret, .open.btn-group .caret { | |
opacity: 1; | |
filter: alpha(opacity=100); | |
} | |
.feedback-btn-inverse .caret { | |
border-top-color: #ffffff; | |
opacity: 0.75; | |
filter: alpha(opacity=75); | |
} | |
.feedback-btn-small .caret { | |
margin-top: 4px; | |
} | |
.feedback-bottom-right { | |
position:fixed; | |
bottom:5px; | |
right:5px; | |
} | |
.feedback-header { | |
padding: 9px 15px; | |
border-bottom: 1px solid #eee; | |
} | |
.feedback-header .feedback-close { | |
margin-top: 2px; | |
} | |
.feedback-body { | |
padding: 15px; | |
} | |
.feedback-body .modal-form { | |
margin-bottom: 0; | |
} | |
.feedback-body textarea { | |
margin: 0; | |
font-size: 100%; | |
vertical-align: middle; | |
overflow: auto; | |
vertical-align: top; | |
font-size: 13px; | |
font-weight: normal; | |
line-height: 18px; | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
display: inline-block; | |
width: 520px; | |
height: 100px; | |
padding: 4px; | |
margin-bottom: 9px; | |
font-size: 13px; | |
line-height: 18px; | |
color: #555555; | |
border: 1px solid #ccc; | |
-webkit-border-radius: 3px; | |
-moz-border-radius: 3px; | |
border-radius: 3px; | |
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
-webkit-transition: border linear 0.2s, box-shadow linear 0.2s; | |
-moz-transition: border linear 0.2s, box-shadow linear 0.2s; | |
-ms-transition: border linear 0.2s, box-shadow linear 0.2s; | |
-o-transition: border linear 0.2s, box-shadow linear 0.2s; | |
transition: border linear 0.2s, box-shadow linear 0.2s; | |
} | |
.feedback-body textarea:focus { | |
border-color: rgba(82, 168, 236, 0.8); | |
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); | |
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); | |
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); | |
outline: 0; | |
outline: thin dotted \9; | |
/* IE6-9 */ | |
} | |
.feedback-footer { | |
padding: 5px 14px 15px 15px; | |
line-height:20px; | |
height:20px; | |
margin-bottom: 0; | |
background-color: #f5f5f5; | |
border-top: 1px solid #ddd; | |
-webkit-border-radius: 0 0 6px 6px; | |
-moz-border-radius: 0 0 6px 6px; | |
border-radius: 0 0 6px 6px; | |
-webkit-box-shadow: inset 0 1px 0 #ffffff; | |
-moz-box-shadow: inset 0 1px 0 #ffffff; | |
box-shadow: inset 0 1px 0 #ffffff; | |
*zoom: 1; | |
} | |
.feedback-footer:before, .feedback-footer:after { | |
display: table; | |
content: ""; | |
} | |
.feedback-footer:after { | |
clear: both; | |
} | |
.feedback-footer .feedback-btn { | |
float: right; | |
margin-left: 5px; | |
margin-bottom: 0; | |
} | |
.feedback-footer .feedback-btn-prev { | |
float: left; | |
margin-left: 0; | |
margin-bottom: 0; | |
} | |
.feedback-glass { | |
position:fixed; | |
z-index:2000; | |
top:0; | |
left:0; | |
width: 100%; | |
height:100%; | |
background: #777; | |
opacity: 0.5; | |
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; | |
filter: alpha(opacity=50); | |
} | |
.feedback-canvas { | |
position: absolute; | |
top: 0; | |
left: 0; | |
pointer-events: none; | |
z-index:1999; | |
} | |
#feedback-blackout-element { | |
background: #000; | |
opacity: 0.8; | |
position:absolute; | |
} | |
.feedback-highlight-element, .feedback-highlighted { | |
position:absolute; | |
-webkit-border-radius: 4px; | |
border-radius: 4px; | |
z-index: 2000; | |
-moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box; | |
-webkit-box-shadow: 0px 0px 8px 0px #000; | |
box-shadow: 0px 0px 8px 0px #000; | |
} | |
.feedback-highlight-element { | |
pointer-events:none; | |
} | |
#feedback-highlight-close { | |
background: #ccc; | |
border:1px solid black; | |
text-align:center; | |
line-height:20px; | |
font-size:20px; | |
font-weight:bold; | |
width:20px; | |
height:20px; | |
position:absolute; | |
cursor:pointer; | |
margin-left:-12px; | |
margin-top:-12px; | |
z-index:2001; | |
-webkit-border-radius: 10px; | |
border-radius: 10px; | |
-webkit-box-shadow: 0px 0px 4px 0px #615e5e; | |
box-shadow: 0px 0px 4px 0px #615e5e; | |
background-color: #c5c5c5; | |
background-image: -webkit-gradient(linear, left top, left bottom, from(#c5c5c5), to(#999999)); | |
background-image: -webkit-linear-gradient(top, #c5c5c5, #999999); | |
background-image: -moz-linear-gradient(top, #c5c5c5, #999999); | |
background-image: -o-linear-gradient(top, #c5c5c5, #999999); | |
background-image: linear-gradient(to bottom, #c5c5c5, #999999); | |
} | |
.feedback-blackedout { | |
background: #000; | |
position:absolute; | |
z-index: 2000; | |
} | |
#feedback-highlight-container { | |
position:absolute; | |
top:0; | |
left:0; | |
pointer-events:none; | |
z-index:2010; | |
} | |
.feedback-animate-toside { | |
top: 100%; | |
left:100%; | |
width: 300px; | |
margin-left:-320px; | |
margin-top: -200px; | |
} | |
.feedback-animate-review { | |
-webkit-transition: all 1s ease 0s; | |
-moz-transition: all 1s ease 0s; | |
-ms-transition: all 1s ease 0s; | |
-o-transition: all 1s ease 0s; | |
top: 50%; | |
left:50%; | |
width: 600px; | |
margin-left:-300px; | |
margin-top: -200px; | |
} | |
.feedback-canvas-complete { | |
-webkit-filter:blur(5px); | |
} | |
.feedback-body canvas { | |
-webkit-border-radius: 4px; | |
border-radius: 4px; | |
border:1px solid #636363; | |
-webkit-box-shadow: 0px 0px 12px 0px #615e5e; | |
box-shadow: 0px 0px 12px 0px #615e5e; | |
position:absolute; | |
} | |
.feedback-browser { | |
margin-left:330px; | |
} | |
.feedback-loader { | |
text-align: center; | |
} | |
.feedback-loader span { | |
display: inline-block; | |
vertical-align: middle; | |
width: 10px; | |
height: 10px; | |
margin: 50px auto; | |
background: black; | |
border-radius: 50px; | |
-webkit-animation: feedback-loader 0.6s infinite alternate; | |
-moz-animation: feedback-loader 0.6s infinite alternate; | |
} | |
.feedback-loader span:nth-of-type(2) { | |
-webkit-animation-delay: 0.2s; | |
-moz-animation-delay: 0.2s; | |
} | |
.feedback-loader span:nth-of-type(3) { | |
-webkit-animation-delay: 0.5s; | |
-moz-animation-delay: 0.5s; | |
} | |
@-webkit-keyframes feedback-loader { | |
0% { | |
width: 10px; | |
height: 10px; | |
opacity: 0.9; | |
-webkit-transform: translateY(0); | |
} | |
100% { | |
width: 24px; | |
height: 24px; | |
opacity: 0.1; | |
-webkit-transform: translateY(-21px); | |
} | |
} | |
@-moz-keyframes feedback-loader { | |
0% { | |
width: 10px; | |
height: 10px; | |
opacity: 0.9; | |
-moz-transform: translateY(0); | |
} | |
100% { | |
width: 24px; | |
height: 24px; | |
opacity: 0.1; | |
-moz-transform: translateY(-21px); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
feedback.js <http://experiments.hertzen.com/jsfeedback/> | |
Copyright (c) 2012 Niklas von Hertzen. All rights reserved. | |
http://www.twitter.com/niklasvh | |
Released under MIT License | |
*/ | |
(function( window, document, undefined ) { | |
if ( window.Feedback !== undefined ) { | |
return; | |
} | |
// log proxy function | |
var log = function( msg ) { | |
window.console.log( msg ); | |
}, | |
// function to remove elements, input as arrays | |
removeElements = function( remove ) { | |
for (var i = 0, len = remove.length; i < len; i++ ) { | |
var item = Array.prototype.pop.call( remove ); | |
if ( item !== undefined ) { | |
if (item.parentNode !== null ) { // check that the item was actually added to DOM | |
item.parentNode.removeChild( item ); | |
} | |
} | |
} | |
}, | |
loader = function() { | |
var div = document.createElement("div"), i = 3; | |
div.className = "feedback-loader"; | |
while (i--) { div.appendChild( document.createElement( "span" )); } | |
return div; | |
}, | |
getBounds = function( el ) { | |
return el.getBoundingClientRect(); | |
}, | |
emptyElements = function( el ) { | |
var item; | |
while( (( item = el.firstChild ) !== null ? el.removeChild( item ) : false) ) {} | |
}, | |
element = function( name, text ) { | |
var el = document.createElement( name ); | |
el.appendChild( document.createTextNode( text ) ); | |
return el; | |
}, | |
// script onload function to provide support for IE as well | |
scriptLoader = function( script, func ){ | |
if (script.onload === undefined) { | |
// IE lack of support for script onload | |
if( script.onreadystatechange !== undefined ) { | |
var intervalFunc = function() { | |
if (script.readyState !== "loaded" && script.readyState !== "complete") { | |
window.setTimeout( intervalFunc, 250 ); | |
} else { | |
// it is loaded | |
func(); | |
} | |
}; | |
window.setTimeout( intervalFunc, 250 ); | |
} else { | |
log("ERROR: We can't track when script is loaded"); | |
} | |
} else { | |
return func; | |
} | |
}, | |
prevButton, | |
nextButton, | |
H2C_IGNORE = "data-html2canvas-ignore", | |
currentPage, | |
modalBody = document.createElement("div"), | |
myOptions; | |
window.Feedback = function( options ) { | |
options = options || {}; | |
// default properties | |
options.label = options.label || "Send Feedback"; | |
options.header = options.header || "Send Feedback"; | |
options.url = options.url || "/"; | |
options.adapter = options.adapter || new window.Feedback.XHR( options.url ); | |
options.prevLabel = options.prevLabel || "Return"; | |
options.nextLabel = options.nextLabel || "Continue"; | |
options.reviewLabel = options.reviewLabel || "Review"; | |
options.sendLabel = options.sendLabel || "Send"; | |
options.closeLabel = options.closeLabel || "Close"; | |
options.reviewFormHeader = options.reviewFormHeader || "Issue"; | |
options.reviewScreenshotHeader = options.reviewScreenshotHeader || "Screenshot"; | |
options.messageSuccess = options.messageSuccess || "Your feedback was sent successfully."; | |
options.messageError = options.messageError || "There was an error sending your feedback to the server."; | |
options.user = options.user || { chid: '', accountId: '', email: ''}; | |
myOptions = options; | |
if (options.pages === undefined ) { | |
options.pages = [ | |
new window.Feedback.Form(), | |
new window.Feedback.Screenshot( options ), | |
new window.Feedback.Review() | |
]; | |
} | |
var button, | |
modal, | |
currentPage, | |
glass = document.createElement("div"), | |
fromPrevious = false, | |
returnMethods = { | |
// open send feedback modal window | |
open: function() { | |
var len = options.pages.length; | |
currentPage = 0; | |
for (; currentPage < len; currentPage++) { | |
// create DOM for each page in the wizard | |
if ( !(options.pages[ currentPage ] instanceof window.Feedback.Review) ) { | |
options.pages[ currentPage ].render(); | |
} | |
} | |
var a = element("a", "×"), | |
modalHeader = document.createElement("div"), | |
// modal container | |
modalFooter = document.createElement("div"); | |
modal = document.createElement("div"); | |
document.body.appendChild( glass ); | |
// modal close button | |
a.className = "feedback-close"; | |
a.onclick = returnMethods.close; | |
a.href = "#"; | |
button.disabled = true; | |
// build header element | |
modalHeader.appendChild( a ); | |
modalHeader.appendChild( element("h3", options.header ) ); | |
modalHeader.className = "feedback-header"; | |
modalBody.className = "feedback-body"; | |
emptyElements( modalBody ); | |
currentPage = 0; | |
modalBody.appendChild( options.pages[ currentPage++ ].dom ); | |
// Next button | |
nextButton = element( "button", options.nextLabel ); | |
nextButton.className = "feedback-btn"; | |
nextButton.onclick = function() { | |
if (currentPage > 0 ) { | |
if ( options.pages[ currentPage - 1 ].end( modal ) === false ) { | |
// page failed validation, cancel onclick | |
return; | |
} | |
if (currentPage == 1) { | |
modalFooter.appendChild( prevButton ); | |
} | |
} | |
emptyElements( modalBody ); | |
if ( currentPage === len ) { | |
returnMethods.send( options.adapter ); | |
} else { | |
options.pages[ currentPage ].start( modal, modalHeader, modalFooter, nextButton ); | |
if ( options.pages[ currentPage ] instanceof window.Feedback.Review ) { | |
// create DOM for review page, based on collected data | |
options.pages[ currentPage ].render( options.pages ); | |
} | |
// add page DOM to modal | |
modalBody.appendChild( options.pages[ currentPage++ ].dom ); | |
// if last page, change button label to send | |
if ( currentPage === len ) { | |
nextButton.firstChild.nodeValue = options.sendLabel; | |
} | |
// if next page is review page, change button label | |
if ( options.pages[ currentPage ] instanceof window.Feedback.Review ) { | |
nextButton.firstChild.nodeValue = options.reviewLabel; | |
} | |
} | |
}; | |
prevButton = element( "button", options.prevLabel ); | |
prevButton.className = "feedback-btn feedback-btn-prev"; | |
prevButton.onclick = function() { | |
window.Feedback.fromPrevious = true; | |
emptyElements( modalBody ); | |
if ( currentPage-- === 2) { | |
prevButton.parentNode.removeChild( prevButton ); | |
} | |
options.pages [currentPage].end( modal ); | |
//currentPage--; | |
options.pages[ currentPage - 1 ].start( modal, modalHeader, modalFooter, nextButton ); | |
if ( options.pages[ currentPage ] instanceof window.Feedback.Review ) { | |
// create DOM for review page, based on collected data | |
options.pages[ currentPage ].render( options.pages ); | |
} | |
if ( options.pages[ currentPage ] instanceof window.Feedback.Screenshot ) { | |
this.h2cDone = true; | |
} | |
currentPage--; | |
// add page DOM to modal | |
modalBody.appendChild( options.pages[ currentPage ].dom ); | |
// if pre-last page page, change button label to next | |
nextButton.firstChild.nodeValue = options.nextLabel; | |
// if next page is review page, change button label | |
if ( options.pages[ currentPage ] instanceof window.Feedback.Review ) { | |
nextButton.firstChild.nodeValue = options.reviewLabel; | |
} | |
currentPage++; | |
}; | |
modalFooter.className = "feedback-footer"; | |
modalFooter.appendChild( nextButton ); | |
//modalFooter.appendChild( prevButton ); | |
modal.className = "feedback-modal"; | |
modal.setAttribute(H2C_IGNORE, true); // don't render in html2canvas | |
modal.appendChild( modalHeader ); | |
modal.appendChild( modalBody ); | |
modal.appendChild( modalFooter ); | |
document.body.appendChild( modal ); | |
}, | |
// close modal window | |
close: function() { | |
button.disabled = false; | |
// remove feedback elements | |
removeElements( [ modal, glass ] ); | |
// call end event for current page | |
if (currentPage > 0 ) { | |
options.pages[ currentPage - 1 ].end( modal ); | |
} | |
// call close events for all pages | |
for (var i = 0, len = options.pages.length; i < len; i++) { | |
options.pages[ i ].close(); | |
} | |
return false; | |
}, | |
// send data | |
send: function( adapter ) { | |
// make sure send adapter is of right prototype | |
if ( !(adapter instanceof window.Feedback.Send) ) { | |
throw new Error( "Adapter is not an instance of Feedback.Send" ); | |
} | |
// fetch data from all pages | |
for (var i = 0, len = options.pages.length, data = [], p = 0, tmp; i < len; i++) { | |
if ( (tmp = options.pages[ i ].data()) !== false ) { | |
data[ p++ ] = tmp; | |
} | |
} | |
nextButton.disabled = true; | |
emptyElements( modalBody ); | |
modalBody.appendChild( loader() ); | |
// send data to adapter for processing | |
adapter.send( data, function( success ) { | |
emptyElements( modalBody ); | |
nextButton.disabled = false; | |
prevButton.parentNode.removeChild( prevButton ); | |
nextButton.firstChild.nodeValue = options.closeLabel; | |
nextButton.onclick = function() { | |
returnMethods.close(); | |
return false; | |
}; | |
if ( success === true ) { | |
modalBody.appendChild( document.createTextNode( options.messageSuccess ) ); | |
} else { | |
modalBody.appendChild( document.createTextNode( options.messageError ) ); | |
} | |
} ); | |
} | |
}; | |
glass.className = "feedback-glass"; | |
glass.style.pointerEvents = "none"; | |
glass.setAttribute(H2C_IGNORE, true); | |
options = options || {}; | |
button = element( "button", options.label ); | |
button.className = "feedback-btn feedback-bottom-right"; | |
button.setAttribute(H2C_IGNORE, true); | |
button.onclick = returnMethods.open; | |
if ( options.appendTo !== null ) { | |
((options.appendTo !== undefined) ? options.appendTo : document.body).appendChild( button ); | |
} | |
return returnMethods; | |
}; | |
window.Feedback.Page = function() {}; | |
window.Feedback.Page.prototype = { | |
render: function( dom ) { | |
this.dom = dom; | |
}, | |
start: function() {}, | |
close: function() {}, | |
data: function() { | |
// don't collect data from page by default | |
return false; | |
}, | |
review: function() { | |
return null; | |
}, | |
end: function() { return true; } | |
}; | |
window.Feedback.Send = function() {}; | |
window.Feedback.Send.prototype = { | |
send: function() {} | |
}; | |
window.Feedback.fromPrevious = false; | |
window.Feedback.Form = function( elements ) { | |
this.elements = elements || [{ | |
type: "textarea", | |
name: myOptions.reviewFormHeader || "Issue", | |
label: null, | |
placeholder: myOptions.placeholder || "Please describe the issue you are experiencing", | |
required: true | |
}]; | |
this.dom = document.createElement("div"); | |
}; | |
window.Feedback.Form.prototype = new window.Feedback.Page(); | |
window.Feedback.Form.prototype.render = function() { | |
var i = 0, len = this.elements.length, item; | |
emptyElements( this.dom ); | |
for (; i < len; i++) { | |
item = this.elements[ i ]; | |
switch( item.type ) { | |
case "textarea": | |
if (item.label != null) this.dom.appendChild( element("label", item.label + ":" + (( item.required === true ) ? " *" : "")) ); | |
item.element = document.createElement('textarea'); | |
item.element.placeholder = item.placeholder; | |
this.dom.appendChild( item.element ); | |
break; | |
} | |
} | |
return this; | |
}; | |
window.Feedback.Form.prototype.end = function() { | |
// form validation | |
var i = 0, len = this.elements.length, item; | |
for (; i < len; i++) { | |
item = this.elements[ i ]; | |
// check that all required fields are entered | |
if ( item.required === true && item.element.value.length === 0) { | |
item.element.className = "feedback-error"; | |
return false; | |
} else { | |
item.element.className = ""; | |
} | |
} | |
return true; | |
}; | |
window.Feedback.Form.prototype.data = function() { | |
if ( this._data !== undefined ) { | |
// return cached value | |
return this._data; | |
} | |
var i = 0, len = this.elements.length, item, data = {}; | |
for (; i < len; i++) { | |
item = this.elements[ i ]; | |
data[ item.name ] = item.element.value; | |
} | |
// cache and return data | |
return ( this._data = data ); | |
}; | |
window.Feedback.Form.prototype.review = function( dom ) { | |
var i = 0, item, len = this.elements.length; | |
for (; i < len; i++) { | |
item = this.elements[ i ]; | |
if (item.element.value.length > 0) { | |
dom.appendChild( element("label", item.name + ":") ); | |
dom.appendChild( document.createTextNode( item.element.value ) ); | |
dom.appendChild( document.createElement( "hr" ) ); | |
} | |
} | |
return dom; | |
}; | |
window.Feedback.Review = function() { | |
this.dom = document.createElement("div"); | |
this.dom.className = "feedback-review"; | |
}; | |
window.Feedback.Review.prototype = new window.Feedback.Page(); | |
window.Feedback.Review.prototype.render = function( pages ) { | |
var i = 0, len = pages.length, item; | |
emptyElements( this.dom ); | |
for (; i < len; i++) { | |
// get preview DOM items | |
pages[ i ].review( this.dom ); | |
} | |
return this; | |
}; | |
window.Feedback.Screenshot = function( options ) { | |
this.options = options || {}; | |
this.options.blackoutClass = this.options.blackoutClass || 'feedback-blackedout'; | |
this.options.highlightClass = this.options.highlightClass || 'feedback-highlighted'; | |
this.h2cDone = false; | |
}; | |
window.Feedback.Screenshot.prototype = new window.Feedback.Page(); | |
window.Feedback.Screenshot.prototype.pauseInterval = 200; | |
window.Feedback.Screenshot.prototype.end = function( modal ){ | |
modal.className = modal.className.replace(/feedback\-animate\-toside/, ""); | |
// remove event listeners | |
document.body.removeEventListener("mousemove", this.mouseMoveEvent, false); | |
document.body.removeEventListener("click", this.mouseClickEvent, false); | |
removeElements( [this.h2cCanvas] ); | |
this.h2cDone = false; | |
}; | |
window.Feedback.Screenshot.prototype.close = function(){ | |
removeElements( [ this.blackoutBox, this.highlightContainer, this.highlightBox, this.highlightClose ] ); | |
//removeElements( document.getElementsByClassName('feedback-highlight-container') ); | |
removeElements( document.getElementsByClassName('feedback-highlight-close') ); | |
removeElements( document.getElementsByClassName('feedback-highlight-element') ); | |
removeElements( document.getElementsByClassName('feedback-blackout-element') ); | |
removeElements( document.getElementsByClassName( this.options.blackoutClass ) ); | |
removeElements( document.getElementsByClassName( this.options.highlightClass ) ); | |
}; | |
window.Feedback.Screenshot.prototype.start = function( modal, modalHeader, modalFooter, nextButton ) { | |
if ( this.h2cDone ) { | |
emptyElements( this.dom ); | |
nextButton.disabled = false; | |
window.Feedback.fromPrevious = false; | |
var $this = this, | |
feedbackHighlightElement = "feedback-highlight-element", | |
dataExclude = "data-exclude"; | |
var action = true; | |
// delegate mouse move event for body | |
this.mouseMoveEvent = function( e ) { | |
// set close button | |
if ( e.target !== previousElement && (e.target.className.indexOf( $this.options.blackoutClass ) !== -1 || e.target.className.indexOf( $this.options.highlightClass ) !== -1)) { | |
var left = (parseInt(e.target.style.left, 10) + parseInt(e.target.style.width, 10)); | |
left = Math.max( left, 10 ); | |
left = Math.min( left, window.innerWidth - 15 ); | |
var top = (parseInt(e.target.style.top, 10)); | |
top = Math.max( top, 10 ); | |
highlightClose.style.left = left + "px"; | |
highlightClose.style.top = top + "px"; | |
removeElement = e.target; | |
clearBox(); | |
previousElement = undefined; | |
return; | |
} | |
// don't do anything if we are highlighting a close button or body tag | |
if (e.target.nodeName === "BODY" || e.target === highlightClose || e.target === modal || e.target === nextButton || e.target === prevButton || e.target.parentNode === modal || e.target.parentNode === modalHeader) { | |
// we are not gonna blackout the whole page or the close item | |
clearBox(); | |
previousElement = e.target; | |
return; | |
} | |
hideClose(); | |
if (e.target !== previousElement ) { | |
previousElement = e.target; | |
window.clearTimeout( timer ); | |
timer = window.setTimeout(function(){ | |
var bounds = getBounds( previousElement ), | |
item; | |
if ( action === false ) { | |
item = blackoutBox; | |
} else { | |
item = highlightBox; | |
item.width = bounds.width; | |
item.height = bounds.height; | |
ctx.drawImage($this.h2cCanvas, window.pageXOffset + bounds.left, window.pageYOffset + bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height ); | |
} | |
// we are only targetting IE>=9, so window.pageYOffset works fine | |
item.setAttribute(dataExclude, false); | |
item.style.left = window.pageXOffset + bounds.left + "px"; | |
item.style.top = window.pageYOffset + bounds.top + "px"; | |
item.style.width = bounds.width + "px"; | |
item.style.height = bounds.height + "px"; | |
}, 100); | |
} | |
}; | |
// delegate event for body click | |
this.mouseClickEvent = function( e ){ | |
e.preventDefault(); | |
if ( action === false) { | |
if ( blackoutBox.getAttribute(dataExclude) === "false") { | |
var blackout = document.createElement("div"); | |
blackout.className = $this.options.blackoutClass; | |
blackout.style.left = blackoutBox.style.left; | |
blackout.style.top = blackoutBox.style.top; | |
blackout.style.width = blackoutBox.style.width; | |
blackout.style.height = blackoutBox.style.height; | |
document.body.appendChild( blackout ); | |
previousElement = undefined; | |
} | |
} else { | |
if ( highlightBox.getAttribute(dataExclude) === "false") { | |
highlightBox.className += " " + $this.options.highlightClass; | |
highlightBox.className = highlightBox.className.replace(/feedback\-highlight\-element/g,""); | |
$this.highlightBox = highlightBox = document.createElement('canvas'); | |
ctx = highlightBox.getContext("2d"); | |
highlightBox.className += " " + feedbackHighlightElement; | |
document.body.appendChild( highlightBox ); | |
clearBox(); | |
previousElement = undefined; | |
} | |
} | |
}; | |
this.highlightClose = element("div", "×"); | |
this.blackoutBox = document.createElement('div'); | |
this.highlightBox = document.createElement( "canvas" ); | |
this.highlightContainer = document.createElement('div'); | |
var timer, | |
highlightClose = this.highlightClose, | |
highlightBox = this.highlightBox, | |
blackoutBox = this.blackoutBox, | |
highlightContainer = this.highlightContainer, | |
removeElement, | |
ctx = highlightBox.getContext("2d"), | |
buttonClickFunction = function( e ) { | |
e.preventDefault(); | |
if (blackoutButton.className.indexOf("active") === -1) { | |
blackoutButton.className += " active"; | |
highlightButton.className = highlightButton.className.replace(/active/g,""); | |
} else { | |
highlightButton.className += " active"; | |
blackoutButton.className = blackoutButton.className.replace(/active/g,""); | |
} | |
action = !action; | |
}, | |
clearBox = function() { | |
clearBoxEl(blackoutBox); | |
clearBoxEl(highlightBox); | |
window.clearTimeout( timer ); | |
}, | |
clearBoxEl = function( el ) { | |
el.style.left = "-5px"; | |
el.style.top = "-5px"; | |
el.style.width = "0px"; | |
el.style.height = "0px"; | |
el.setAttribute(dataExclude, true); | |
}, | |
hideClose = function() { | |
highlightClose.style.left = "-50px"; | |
highlightClose.style.top = "-50px"; | |
}, | |
blackoutButton = element("a", "Blackout"), | |
highlightButton = element("a", "Highlight"), | |
previousElement; | |
modal.className += ' feedback-animate-toside'; | |
highlightClose.id = "feedback-highlight-close"; | |
highlightClose.addEventListener("click", function(){ | |
removeElement.parentNode.removeChild( removeElement ); | |
hideClose(); | |
}, false); | |
document.body.appendChild( highlightClose ); | |
this.h2cCanvas.className = 'feedback-canvas'; | |
document.body.appendChild( this.h2cCanvas); | |
var buttonItem = [ highlightButton, blackoutButton ]; | |
this.dom.appendChild( element("p", "Highlight or blackout important information") ); | |
// add highlight and blackout buttons | |
for (var i = 0; i < 2; i++ ) { | |
buttonItem[ i ].className = 'feedback-btn feedback-btn-small ' + (i === 0 ? 'active' : 'feedback-btn-inverse'); | |
buttonItem[ i ].href = "#"; | |
buttonItem[ i ].onclick = buttonClickFunction; | |
this.dom.appendChild( buttonItem[ i ] ); | |
this.dom.appendChild( document.createTextNode(" ") ); | |
} | |
highlightContainer.id = "feedback-highlight-container"; | |
highlightContainer.style.width = this.h2cCanvas.width + "px"; | |
highlightContainer.style.height = this.h2cCanvas.height + "px"; | |
this.highlightBox.className += " " + feedbackHighlightElement; | |
this.blackoutBox.id = "feedback-blackout-element"; | |
document.body.appendChild( this.highlightBox ); | |
highlightContainer.appendChild( this.blackoutBox ); | |
document.body.appendChild( highlightContainer ); | |
// bind mouse delegate events | |
document.body.addEventListener("mousemove", this.mouseMoveEvent, false); | |
document.body.addEventListener("click", this.mouseClickEvent, false); | |
} else { | |
// still loading html2canvas | |
var args = arguments, | |
$this = this; | |
if ( nextButton.disabled !== true) { | |
this.dom.appendChild( loader() ); | |
} | |
nextButton.disabled = true; | |
window.setTimeout(function(){ | |
if (window.Feedback.fromPrevious) { | |
$this.h2cDone = true; | |
$this.pauseInterval = 200; | |
} else { | |
$this.pauseInterval += 100; | |
} | |
$this.start.apply( $this, args ); | |
}, this.pauseInterval); | |
} | |
}; | |
window.Feedback.Screenshot.prototype.render = function() { | |
this.dom = document.createElement("div"); | |
// execute the html2canvas script | |
var script, | |
$this = this, | |
options = this.options, | |
runH2c = function(){ | |
try { | |
options.onrendered = options.onrendered || function( canvas ) { | |
$this.h2cCanvas = canvas; | |
$this.h2cDone = true; | |
}; | |
window.html2canvas([ document.body ], options); | |
} catch( e ) { | |
$this.h2cDone = true; | |
log("Error in html2canvas: " + e.message); | |
} | |
}; | |
if ( window.html2canvas === undefined && script === undefined ) { | |
// let's load html2canvas library while user is writing message | |
script = document.createElement("script"); | |
script.src = options.h2cPath || "libs/html2canvas.js"; | |
script.onerror = function() { | |
log("Failed to load html2canvas library, check that the path is correctly defined"); | |
}; | |
script.onload = (scriptLoader)(script, function() { | |
if (window.html2canvas === undefined) { | |
log("Loaded html2canvas, but library not found"); | |
return; | |
} | |
window.html2canvas.logging = window.Feedback.debug; | |
runH2c(); | |
}); | |
var s = document.getElementsByTagName('script')[0]; | |
s.parentNode.insertBefore(script, s); | |
} else { | |
// html2canvas already loaded, just run it then | |
runH2c(); | |
} | |
return this; | |
}; | |
window.Feedback.Screenshot.prototype.data = function() { | |
if ( this._data !== undefined ) { | |
return this._data; | |
} | |
if ( this.h2cCanvas !== undefined ) { | |
var ctx = this.h2cCanvas.getContext("2d"), | |
canvasCopy, | |
copyCtx, | |
radius = 5; | |
ctx.fillStyle = "#000"; | |
// draw blackouts | |
Array.prototype.slice.call( document.getElementsByClassName('feedback-blackedout'), 0).forEach( function( item ) { | |
var bounds = getBounds( item ); | |
ctx.fillRect( bounds.left, bounds.top, bounds.width, bounds.height ); | |
}); | |
// draw highlights | |
var items = Array.prototype.slice.call( document.getElementsByClassName('feedback-highlighted'), 0); | |
if (items.length > 0 ) { | |
// copy canvas | |
canvasCopy = document.createElement( "canvas" ); | |
copyCtx = canvasCopy.getContext('2d'); | |
canvasCopy.width = this.h2cCanvas.width; | |
canvasCopy.height = this.h2cCanvas.height; | |
copyCtx.drawImage( this.h2cCanvas, 0, 0 ); | |
ctx.fillStyle = "#777"; | |
ctx.globalAlpha = 0.5; | |
ctx.fillRect( 0, 0, this.h2cCanvas.width, this.h2cCanvas.height ); | |
ctx.beginPath(); | |
items.forEach( function( item ) { | |
var x = parseInt(item.style.left, 10), | |
y = parseInt(item.style.top, 10), | |
width = parseInt(item.style.width, 10), | |
height = parseInt(item.style.height, 10); | |
ctx.moveTo(x + radius, y); | |
ctx.lineTo(x + width - radius, y); | |
ctx.quadraticCurveTo(x + width, y, x + width, y + radius); | |
ctx.lineTo(x + width, y + height - radius); | |
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); | |
ctx.lineTo(x + radius, y + height); | |
ctx.quadraticCurveTo(x, y + height, x, y + height - radius); | |
ctx.lineTo(x, y + radius); | |
ctx.quadraticCurveTo(x, y, x + radius, y); | |
}); | |
ctx.closePath(); | |
ctx.clip(); | |
ctx.globalAlpha = 1; | |
ctx.drawImage(canvasCopy, 0,0); | |
} | |
// to avoid security error break for tainted canvas | |
try { | |
// cache and return data | |
return ( this._data = this.h2cCanvas.toDataURL() ); | |
} catch( e ) {} | |
} | |
}; | |
window.Feedback.Screenshot.prototype.review = function( dom ) { | |
var data = this.data(); | |
if ( data !== undefined ) { | |
var img = new Image(); | |
img.src = data; | |
img.style.width = "300px"; | |
dom.appendChild( element("label", myOptions.reviewScreenshotHeader + " :") ); | |
dom.appendChild( img ); | |
} | |
}; | |
window.Feedback.XHR = function( url ) { | |
this.xhr = new XMLHttpRequest(); | |
this.url = url; | |
}; | |
window.Feedback.XHR.prototype = new window.Feedback.Send(); | |
window.Feedback.XHR.prototype.send = function( data, callback ) { | |
var xhr = this.xhr; | |
xhr.onreadystatechange = function() { | |
if( xhr.readyState == 4 ){ | |
callback( (xhr.status === 200) ); | |
} | |
}; | |
xhr.open( "POST", this.url, true); | |
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); | |
xhr.send( "data=" + encodeURIComponent( window.JSON.stringify( data ) ) ); | |
}; | |
})( window, document ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<!-- saved from url=(0054)http://twitter.github.com/bootstrap/examples/hero.html --> | |
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | |
<meta charset="utf-8"> | |
<title>Bootstrap, from Twitter</title> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<meta name="description" content=""> | |
<meta name="author" content=""> | |
<!-- Le styles --> | |
<link rel="stylesheet" href="css/bootstrap.css" type="text/css" media="screen" /> | |
<link rel="stylesheet" href="css/feedback.css" type="text/css" media="screen" /> | |
<style type="text/css"> | |
body { | |
padding-top: 60px; | |
padding-bottom: 40px; | |
} | |
</style> | |
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements --> | |
<!--[if lt IE 9]> | |
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> | |
<![endif]--> | |
</head> | |
<body> | |
<div class="navbar navbar-inverse navbar-fixed-top"> | |
<div class="navbar-inner"> | |
<div class="container"> | |
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
</a> | |
<a class="brand" href="#_">Feedback.js Example</a> | |
<div class="nav-collapse collapse"> | |
<ul class="nav"> | |
<li class="active"><a href="#_">Home</a></li> | |
<li><a href="#_">About</a></li> | |
<li><a href="#_">Contact</a></li> | |
</ul> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="container"> | |
<div class="hero-unit"> | |
<h1>Feedback.js</h1> | |
<p>This page serves as an example for how feedback.js is used. Click on the Feedback button on the bottom right of the screen to try it out</p> | |
<p><a class="btn btn-primary btn-large">Learn more »</a></p> | |
</div> | |
<!-- Example row of columns --> | |
<div class="row"> | |
<div class="span4"> | |
<h2>Heading</h2> | |
<p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p> | |
<p><a class="btn" href="#_">View details »</a></p> | |
</div> | |
<div class="span4"> | |
<h2>Heading</h2> | |
<p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p> | |
<p><a class="btn" href="#_">View details »</a></p> | |
</div> | |
<div class="span4"> | |
<h2>Heading</h2> | |
<p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p> | |
<p><a class="btn" href="#_">View details »</a></p> | |
</div> | |
</div> | |
<hr> | |
<footer> | |
<p>Feedback.js - tell us more!</p> | |
</footer> | |
</div> <!-- /container --> | |
<!-- Le javascript --> | |
<script src="js/jquery.js"></script> | |
<script src="js/feedback.js"></script> | |
<script type="text/javascript"> | |
$(document).ready(function() { | |
Feedback({ | |
label: 'Feedback', | |
header: 'Send us a feedback', | |
prevLabel: 'Back', | |
nextLabel: 'Next', | |
reviewLabel: 'Next', | |
sendLabel: '', | |
placeholder: 'Give us your feedback or ask for help...', | |
closeLabel: '', | |
reviewFormHeader: 'Your feedback', | |
reviewScreenshotHeader: 'Your screenshot', | |
h2cPath: 'js/html2canvas.js' | |
}); | |
}); | |
</script> | |
</body></html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment