I am integrating heartland as a payment gateway in my application.
Here's my code.
When I try to update the zip code it will rerender and update the amount.
I want to update the value of fields: submit: value of embedded HPS.
Currently, it's in componentDidUpdate so it is now duplicating the fields as well.
How update the value and keep all the state including card, CVV, etc details?
I don't have any state value of these fields and once I somehow rerender the component it will vanish the field values.
Heartland Documentation
componentDidUpdate() {
console.log('render')
this.state.hps = new Heartland.HPS({
publicKey: 'pkapi_cert_jKc1FtuyAydZhZfbB3',
type: 'iframe',
// Configure the iframe fields to tell the library where
// the iframe should be inserted into the DOM and some
// basic options
fields: {
cardNumber: {
target: 'iframesCardNumber',
placeholder: '•••• •••• •••• ••••'
},
cardExpiration: {
target: 'iframesCardExpiration',
placeholder: 'MM / YYYY'
},
cardCvv: {
target: 'iframesCardCvv',
placeholder: 'CVV'
},
submit: {
value: `Pay ${this.state.amount}` || "Pay 0",
target: 'iframesSubmit'
}
},
// Collection of CSS to inject into the iframes.
// These properties can match the site's styles
// to create a seamless experience.
style: {
'input': {
'background': '#fff',
'border': '1px solid',
'border-color': '#bbb3b9 #c7c1c6 #c7c1c6',
'box-sizing': 'border-box',
'font-family': 'serif',
'font-size': '16px',
'line-height': '1',
'margin': '0 .5em 0 0',
'max-width': '100%',
'outline': '0',
'padding': '0.5278em',
'vertical-align': 'baseline',
'height' : '50px',
'width' : '100% !important'
},
'#heartland-field': {
'font-family':'sans-serif',
'box-sizing':'border-box',
'display': 'block',
'height': '50px',
'padding': '6px 12px',
'font-size': '14px',
'line-height': '1.42857143',
'color': '#555',
'background-color': '#fff',
'border': '1px solid #ccc',
'border-radius': '0px',
'-webkit-box-shadow': 'inset 0 1px 1px rgba(0,0,0,.075)',
'box-shadow': 'inset 0 1px 1px rgba(0,0,0,.075)',
'-webkit-transition': 'border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s',
'-o-transition': 'border-color ease-in-out .15s,box-shadow ease-in-out .15s',
'transition': 'border-color ease-in-out .15s,box-shadow ease-in-out .15s',
'width' : '100%'
},
'#heartland-field[name=submit]': {
'background-color':'#36b46e',
'font-family':'sans-serif',
'text-transform':'uppercase',
'color':'#ffffff',
'border':'0px solid transparent'
} ,
'#heartland-field[name=submit]:focus': {
'color':'#ffffff',
'background-color':'#258851',
'outline':'none'
} ,
'#heartland-field[name=submit]:hover': {
'background-color':'#258851'
} ,
'#heartland-field-wrapper #heartland-field:focus' : {
'border':'1px solid #3989e3',
'outline':'none',
'box-shadow':'none',
'height':'50px'
},
'heartland-field-wrapper #heartland-field' : {
'height':'50px'
},
'input[type=submit]' : {
'box-sizing':'border-box',
'display': 'inline-block',
'padding': '6px 12px',
'margin-bottom': '0',
'font-size': '14px',
'font-weight': '400',
'line-height': '1.42857143',
'text-align': 'center',
'white-space': 'nowrap',
'vertical-align': 'middle',
'-ms-touch-action': 'manipulation',
'touch-action': 'manipulation',
'cursor': 'pointer',
'-webkit-user-select': 'none',
'-moz-user-select': 'none',
'-ms-user-select': 'none',
'user-select': 'none',
'background-image': 'none',
'border': '1px solid transparent',
'border-radius': '4px',
'color': '#fff',
'background-color': '#337ab7',
'border-color': '#2e6da4'
},
'#heartland-field[placeholder]' :{
'letter-spacing':'3px'
},
'#heartland-field[name=cardCvv]' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/cvv1.png?raw=true) no-repeat right',
'background-size' :'63px 40px',
},
'input#heartland-field[name=cardNumber]' : {
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-inputcard-blank#2x.png?raw=true) no-repeat right',
'background-size' :'55px 35px'},
'#heartland-field.invalid.card-type-visa' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-saved-visa#2x.png?raw=true) no-repeat right',
'background-size' :'83px 88px',
'background-position-y':'-44px'
},
'#heartland-field.valid.card-type-visa' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-saved-visa#2x.png?raw=true) no-repeat right top',
'background-size' :'82px 86px'
},
'#heartland-field.invalid.card-type-discover' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-saved-discover#2x.png?raw=true) no-repeat right',
'background-size' :'85px 90px',
'background-position-y' : '-44px'
},
'#heartland-field.valid.card-type-discover' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-saved-discover#2x.png?raw=true) no-repeat right',
'background-size' :'85px 90px',
'background-position-y' : '1px'
},
'#heartland-field.invalid.card-type-amex' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-savedcards-amex#2x.png?raw=true) no-repeat right',
'background-size' :'50px 90px',
'background-position-y':'-44px'
},
'#heartland-field.valid.card-type-amex' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-savedcards-amex#2x.png?raw=true) no-repeat right top',
'background-size' :'50px 90px'
},
'#heartland-field.invalid.card-type-mastercard' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-saved-mastercard.png?raw=true) no-repeat right',
'background-size' :'62px 105px',
'background-position-y':'-52px'
},
'#heartland-field.valid.card-type-mastercard' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-saved-mastercard.png?raw=true) no-repeat right',
'background-size' :'62px 105px',
'background-position-y':'-1px'
},
'#heartland-field.invalid.card-type-jcb' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-saved-jcb#2x.png?raw=true) no-repeat right',
'background-size' :'55px 94px',
'background-position-y':'-44px'
},
'#heartland-field.valid.card-type-jcb' :{
'background':'transparent url(https://github.com/hps/heartland-php/blob/master/examples/end-to-end/assets/images/ss-saved-jcb#2x.png?raw=true) no-repeat right top',
'background-size' :'55px 94px',
'background-position-y':'2px'
},
'input#heartland-field[name=cardNumber]::-ms-clear' : {
'display':'none'
}
},
// Callback when a token is received from the service
onTokenSuccess: function (resp) {
alert('Here is a single-use token: ' + resp.token_value);
},
// Callback when an error is received from the service
onTokenError: function (resp) {
alert('There was an error: ' + resp.error.message);
},
// Callback when an event is fired within an iFrame
onEvent: function (ev) {
console.log(ev);
}
});
}
Related
I have this installed react-particles-js, everything works fine as I see, but now I have created some custom design, and assigned it to the Particle via it params, just like this:
<Particles
params={{
particles: {
number: { value: 35, density: { enable: true, value_area: 800 } },
color: {
value: [
'BB4D10',
'#820E42',
'#BD740F',
'#248592',
'#5F4DAF',
'#8BA00F',
],
},
shape: {
type: 'circle',
stroke: { width: 0, color: '#000000' },
polygon: { nb_sides: 3 },
image: { src: 'img/github.svg', width: 100, height: 100 },
},
opacity: {
value: 1.5,
random: false,
anim: {
enable: false,
speed: 1,
opacity_min: 0.1,
sync: false,
},
},
size: {
value: 9,
random: true,
anim: {
enable: false,
speed: 43.15684315684316,
size_min: 0.1,
sync: false,
},
},
line_linked: {
enable: true,
distance: 100.82952832645452,
color: '#ffffff',
opacity: 1.4,
width: 1,
},
move: {
enable: true,
speed: 2,
direction: 'none',
random: true,
straight: false,
out_mode: 'out',
bounce: false,
attract: { enable: false, rotateX: 600, rotateY: 1200 },
},
},
interactivity: {
detect_on: 'canvas',
events: {
onhover: { enable: true, mode: 'bubble' },
onclick: { enable: false, mode: 'push' },
resize: true,
},
modes: {
grab: { distance: 400, line_linked: { opacity: 1 } },
bubble: {
distance: 109.63042366068159,
size: 13,
duration: 2,
opacity: 8,
speed: 3,
},
repulse: { distance: 200, duration: 0.4 },
push: { particles_nb: 4 },
remove: { particles_nb: 2 },
},
},
retina_detect: true,
}}
style={styling}
/>
After that, I'm trying to add a background color to make it look correctly, but as I can see the styling which I try to pass to the particle it just doesn't work, at least the position applies.
const styling = {
backgroundColor: '#2a2e31',
position: 'absolute',
width: '10%',
};
There are several ways to control the styling:
You can provide a className prop for canvas wrapper, and width prop for the width of canvas:
<Particles
...
style={styling}
width="10%"
className="particles-wrapper"
/>
And, write the CSS:
.particles-wrapper {
background-color: #2a2e31;
height: 100%;
width: 10%; // You may need this or may not depending on your requirement
}
Or, you can add a new div which would wrap the <Particles .. /> and set styling for this div as by default canvas is transparent.
Or, you can use canvasClassName prop and set the style for this class.
Here is a snapshot after using the 1st method from above:
The reason that we need to pass width, height separately is, as seen in source code, those present in props.style is being overwritten like this:
style={{
...this.props.style,
width,
height
}}
The easiest way to set a background to the particles is using the background option.
<Particles params={{
background: {
color: "#000"
},
/* all other options you set */
}} />
This will set a background to the canvas. If you need a transparent one use #ajeet-shah answer.
I'm writing a code that will popup a text wrapped in array and display each text with forEach function. Here's the sample code.
var hotSpots =
[
{
id : 'svc1', // 1
text: 'Radiator Repair',
spotPosition: 'left: 0em; top: 14.5em',
textPosition: 'left: -4em;',
arrowPosition: 'left: 0.5em;',
},
{
id : 'svc2', // 2
text: 'Headlight Blub Replacement / Repair',
spotPosition: 'left: 3em; top: 13em',
textPosition: 'left: -15em;',
arrowPosition: 'left: 12em;',
},
{
id : 'svc3', // 3
text: 'Engine Full Service / Repair',
spotPosition: 'left: 9em; top: 9.5em',
textPosition: 'left: -8em;',
arrowPosition: 'left: 3em;',
},
{
id : 'svc3b', // 8
text: 'Oil Charge & Lube',
spotPosition: 'left: 14em; top: 8.5em',
textPosition: 'left: -6em;',
arrowPosition: 'left: 3em;',
},
{
id : 'svc4', // 4
text: 'Wiper / Wiper Motor Repair',
spotPosition: 'left: 20em; top: 8em',
textPosition: 'left: -0.5em;',
arrowPosition: 'right: 12em;',
},
{
id : 'svc5', // 9
text: 'Windsheild Repair / Replace',
spotPosition: 'left: 28em; top: 5em',
textPosition: 'right: -10em;',
arrowPosition: 'right: 6em;',
},
{
id : 'svc6', // 11
text: 'Window Regulators',
spotPosition: 'left: 35em; top: 6em',
textPosition: 'right: -7.8em;',
arrowPosition: 'right: 6em;',
},
{
id : 'svc7',
text: 'Drive Axle Service',
spotPosition: 'right: 3em; top: 6em',
textPosition: 'right: -7.8em;',
arrowPosition: 'right: 6em;',
},
{
id : 'svc8',
text: 'Tune-ups for better Fuel Efficentcy',
spotPosition: 'right: 11.2em; top: 10.2em',
textPosition: 'left: -7.5em;',
arrowPosition: 'left: -1.6em;',
},
{
id : 'svc9',
text: 'Alignments',
spotPosition: 'right: 1.7em; top: 13em',
textPosition: 'left: -2em;',
arrowPosition: 'left: -1.6em;',
},
{
id : 'svc10', // 13
text: 'Exhaust Pipe and Mufflers Install / Repair',
spotPosition: 'right: 3em; top: 20.5em',
textPosition: 'left: -9em;',
arrowPosition: 'left: -1.6em;',
},
{
id : 'svc10b', // 10
text: 'ABS Brakes',
spotPosition: 'right: 15.8em; top: 19em;',
textPosition: 'left: -2.2em;',
arrowPosition: 'left: -1.6em;',
},
{
id : 'svc11', //
text: 'Heating Systems',
spotPosition: 'left: 38em; top: 11em',
textPosition: 'left: -3.2em;',
arrowPosition: 'left: -1.6em;',
},
{
id : 'svc12',
text: 'A/C Service',
spotPosition: 'left: 12.5em; bottom: 4em',
textPosition: 'left: -2em;',
arrowPosition: 'left: -1.6em;',
},
{
id : 'svc13', // 6
text: 'Tire Repair and Sales',
spotPosition: 'left: 14em; bottom: 11.4em',
textPosition: 'left: -4.3em;',
arrowPosition: 'left: -1.6em;',
},
{
id : 'svc14', // 7
text: 'Brake Systems',
spotPosition: 'left: 11.5em; bottom: 7em',
textPosition: 'left: -3em;',
arrowPosition: 'left: -1.6em;',
},
{
id : 'svc15', // 5
text: 'Suspension & Steering',
spotPosition: 'left: 14em; bottom: 13em',
textPosition: 'left: -2em;',
arrowPosition: 'left: -7em;',
}
];
Here's how I extracted the data from var hotSpots.
hotSpots.forEach(function(data){
var element = data.id;
var popups = setInterval(function(i){
$('.svchotSpotWrapper').removeClass('show');
$('#'+element).addClass('show');
}, 4000 + offset);
offset += 4000;
$(document).on('click', '#'+element, function(){
$('.svchotSpotWrapper').removeClass('show');
$(this).addClass('show');
clearInterval(popups);
});
});
The code above will output multiple dots, and what I am trying to achieve is when I click on a certain dot, the interval will stop.
The following code is what I already tried:
$(document).on('click', '#'+element, function(){
$('.svchotSpotWrapper').removeClass('show');
$(this).addClass('show');
clearInterval(popups);
});
However, it doesn't stop the interval.
You could pass popups variable in jQuery as a parameter and access it in event.data for individual click events:
hotSpots.forEach(function(data) {
var element = data.id;
var popups = setInterval(function(i) {
$('.svchotSpotWrapper').removeClass('show');
$('#' + element).addClass('show');
}, 4000 + offset);
offset += 4000;
$(document).on('click', '#' + element, { popupInterval: popups },
function(event) {
$('.svchotSpotWrapper').removeClass('show');
$(this).addClass('show');
clearInterval(event.data.popupInterval);
});
});
EDIT
In order to clear the multiple intervals you may have collect them in an array and clear them all at once:
var popups = [];
hotSpots.forEach(function(data) {
var element = data.id;
var popup = window.setInterval(function(i) {
$('.svchotSpotWrapper').removeClass('show');
$('#' + element).addClass('show');
}, 400 + offset);
popups.push(popup);
offset += 400;
$(document).on('click', '#' + element, function(event) {
$('.svchotSpotWrapper').removeClass('show');
$(this).addClass('show');
popups.forEach(function(popup) {
clearInterval(popup);
});
});
});
I want to change the chat avatar, and the avatar of the bot, but setting the backgroundImage doesn't work
var styleSet = window.WebChat.createStyleSet({
backgroundColor: '#f3f3f3',
bubbleBackground: '#FFFFFF',
bubbleBorderRadius: 5,
bubbleTextColor: 'Black',
bubbleFromUserBackground: '#3a8dde',
bubbleFromUserBorderRadius: 5,
bubbleFromUserTextColor: 'White',
});
styleSet.avatar = {
alignItems: 'center',
borderRadius: '50%',
color: 'white',
backgroundColor: 'gray',
display: 'flex',
height: "50px",
justifyContent: 'center',
overflow: 'hidden',
width: "50px"
};
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({token: 'My.Secret.token'}),
//styles
styleSet: styleSet,
botAvatarInitials: 'BF',
userAvatarInitials: 'WC'
}, document.getElementById('webchat'));
There is currently no solution for setting background images, but there is a workaround you can use with idiosyncratic styling, originally shared here on GitHub.
import { createStyleSet } from 'botframework-webchat;
const styleSet = createStyleSet({});
styleSet.avatar = {
...styleSet.avatar,
'&.from-user': {
backgroundImage:'url(\'https://github.com/compulim.png?size=64\')'
},
'&:not(.from-user)': {
backgroundImage:'url(\'https://learn.microsoft.com/en-us/azure/bot-service/v4sdk/media/logo_bot.svg?view=azure-bot-service-4.0\')' }
};
};
<ReactWebChat
botAvatarInitials= ' '
userAvatarInitials= ' '
styleSet={styleSet}`
/>
In JavaScript, you can do the following:
const styleSet = window.WebChat.createStyleSet();
styleSet.avatar = {
...styleSet.avatar,
'&.from-user': {
backgroundImage:'url(\'https://github.com/compulim.png?size=64\')'
},
'&:not(.from-user)': {
backgroundImage:'url(\'https://learn.microsoft.com/en-us/azure/bot-service/v4sdk/media/logo_bot.svg?view=azure-bot-service-4.0\')' }
};
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
styleSet,
botAvatarInitials: ' ',
userAvatarInitials: ' '
}, document.getElementById('webchat'));
I have been researching this for the past hour and I cannot seem to figure out what is wrong. I would like to make a simple plugin that allows for multiple instances each with their own settings I am not super versed in javascript so I am not using the object/prototype method.
When I run this plugin on two different elements, each with their own settings, only the last settings is being used as seen by the console.log
Here is what I have:
jQuery.fn.lighthouse = function(config) {
config = $.extend({}, jQuery.fn.lighthouse.config, config);
config.openDuration = config.openDuration || config.duration;
config.closeDuration = config.closeDuration || config.duration;
return this.each(function() {
var containers = $(this);
$(containers).click(open);
$(config.closeSelector).click(close);
console.log(config.contentType);
$(containers).each(function() {
if (config.contentType === 'img' && $(this).prop('tagName') === 'A') {
var href = $(this).href,
src = $(this).children('img').src;
if (href !== src) {
}
}
});
// Needs the container object
function open(link) {
link.preventDefault();
var current = {
close: $(this).children(config.closeSelector),
background: $(this).children(config.backgroundSelector),
container: $(this),
child: $(this).children(config.childSelector)
};
console.log($(current.child).is(':hidden'));
if($(current.child).is(':hidden')) {
link.preventDefault();
}
$(current.container).append('<div class="background"></div>').css({
background: config.background,
width: '100%',
height: '100%',
position: 'fixed',
zIndex: '2',
opacity: config.backgroundOpacity,
display: 'none'
}).fadeIn(config.secondaryDuration);
$(current.child).css({
position: 'fixed',
display: 'none',
width: '150px',
height: '150px',
left: current.container.offset().left,
top: current.container.offset().top,
zIndex: '3'
}).fadeIn(config.secondaryDuration).animate({
width: '100%',
height: '100%',
top: '0',
left: '0'
}, config.openDuration, function () {
$(current.container).append('<a class=".close">X</a>').css({
background: 'white',
color: 'black',
width: '50px',
height: '50px',
lineHeight: '50px',
textAlign: 'center',
position: 'absolute',
top: '0',
right: '0',
display: 'none'
}).fadeIn(config.secondaryDuration);
});
}
// Needs the close object
function close(link) {
link.preventDefault();
var current = {
close: $(this),
background: $(this).siblings(config.backgroundSelector),
container: $(this).parent(config.containerSelector),
child: $(current.containter).children(config.childSelector)
};
$(current.close).fadeOut(config.secondaryDuration).remove();
$(current.close).fadeOut(config.secondaryDuration).remove();
$(current.child).animate({
height: current.containter.height(),
width: current.containter.width(),
top: current.containter.offset().top,
left: current.containter.offset().left
}, config.closeDuration, function () {
$(current.child).animate({
opacity: '0',
}, config.secondaryDuration).css({
display: 'none',
zIndex: 'auto'
});
});
}
});
}
jQuery.fn.lighthouse.config = {
containerSelector: '.lighthouse',
childSelector: 'div',
closeSelector: '.close',
backgroundSelector: '.background',
captionSelector: '.caption',
duration: 350,
openDuration: null,
closeDuration: null,
secondaryDuration: 100,
background: 'rgb(230, 230, 230)',
backgroundOpacity: '0.7',
contentType: 'img'
}
This is what I am calling it with:
$('.image').lighthouse();
$('.click').lighthouse({
childSelector: '.site',
contentType: 'html'
});
Here is the jsfiddle: http://jsfiddle.net/yK9ad/
The proper output of console.log should be:
img
html
Any ideas? Thanks in advance for the help!
I think you are missing the class attribute for the anchor containing <img/> tag. Please see below
<a class="image" href="http://placehold.it/900x800&text=Image">
<img src="http://placehold.it/300x200&text=Image" />
<span class="caption">
test
</span>
</a>
The updated fiddle - http://jsfiddle.net/yK9ad/2/
I could see the following in the console.
img
html
Merged with form submit.
In this function, based on the value of an input, the form submit is true/false. Why isn't return true working in this function?
<script>
$(".askInput").keyup(function() {
if ($(this).val().indexOf("?") != -1) {
$(this).css({"color" : "#00bfff", 'border-top-right-radius' : '0px', 'border-bottom-right-radius' : '0px', '-moz-border-top-right-radius' : '0px', '-moz-border-bottom-right-radius' : '0px', '-webkit-border-top-right-radius' : '0px', '-webkit-border-bottom-right-radius' : '0px'});
$('.searchEnter').stop().animate({
marginLeft: "310px"
}, 200 );
$('.form1').submit(function () {
return false;
});
} else {
$(this).css({"color" : "#333", 'border-top-right-radius' : '5px', 'border-bottom-right-radius' : '5px', '-moz-border-top-right-radius' : '5px', '-moz-border-bottom-right-radius' : '5px', '-webkit-border-top-right-radius' : '5px', '-webkit-border-bottom-right-radius' : '5px'});
$('.searchEnter').stop().animate({
marginLeft: "250px"
}, 200 );
$('.form1').submit(function () {
return true;
});
}
});
</script>