SendGrid API Dynamic - can't get Unsubscribe to work - sendgrid

I just set-up a dynamic email with sendgrid and am using the API to fill it out based on my customer data.
I've gotten everything to work except the unsubscribe part.
I have an unsubscribe block at the bottom of my email. In the code editor, the code looks like this:
<div data-role="module-unsubscribe" class="module" role="module" data-type="unsubscribe" style="color:#444444; font-size:12px; line-height:20px; padding:16px 16px 16px 16px; text-align:center;" data-muid="67cd14f7-ddbf-421a-a070-57b3b3e6ccac"><p style="font-size:12px; line-height:20px;"><a class="Unsubscribe--unsubscribeLink" href="{{unsubscribe}}" target="_blank" style="">Unsubscribe</a></p></div></td>
I didn't edit the code, that's just how it came. But when I send the email (test or otherwise), the unsubscribe is not a link. Do I need to pass something for {{unsubscribe}} in the API request? If so, what would I pass?
Thanks for your help!

When you send an email with unsubscribe links, you need to include the unsubscribe group in the API request.
For example:
client
.send({
to: "hello#example.com",
from: "me#example.org",
templateId: "YOUR_TEMPLATE_ID",
dynamicTemplateData: { ... },
asm: {
groupId: "YOUR_UNSUBSCRIBE_GROUP_ID"
}
})
Make sure the asm key is in the root object, not in personalizations.

<div data-role="module-unsubscribe" class="module" role="module" data-type="unsubscribe" style="color:#444444; font-size:12px; line-height:20px; padding:16px 16px 16px 16px; text-align:center;" data-muid="67cd14f7-ddbf-421a-a070-57b3b3e6ccac"><p style="font-size:12px; line-height:20px;"><a class="Unsubscribe--unsubscribeLink" href="{{unsubscribe}}" target="_blank" style="">Unsubscribe</a></p></div></td>

Related

VueJS plugin rendering problems. Vue Formulate

So i am not profeccional in vueJs that`s why if you need some more additional information just write in coments i will try to provide it...
This is the way that i intalling this plugin
import VueFormulate from '#braid/vue-formulate';
Vue.use(VueFormulate);
and in my template where i want to use this plugin
<FormulateInput
type="email"
name="email"
label="Enter your email address"
help="We’ll send you an email when your ice cream is ready"
validation="required|email"
/>
but on browser page there is nothing and what i see in rendered page tree
<formulateinput
type="email"
name="email"
label="Enter your email address"
help="We’ll send you an email when your ice cream is ready"
validation="required|email">
</formulateinput>
So as i can see it is not rendered.
A little interting thing. When component where i whant to use plugin mounted then output in console plugin object, and it is exits
mounted() {
console.log(VueFormulate);
}
screen from console
can you please help me to find what i miss? :3
The main problem was in template tags.
And VueFormulate component in my template must be lower-cased, hyphen separated and with a closing tag
<formulate-input
type="email"
name="email"
label="Enter your email address"
help="We’ll send you an email when your ice cream is ready"
validation="required|email"
></formulate-input>
instead of
<FormulateInput
type="email"
name="email"
label="Enter your email address"
help="We’ll send you an email when your ice cream is ready"
validation="required|email"
/>
More information about syntax style:
https://v2.vuejs.org/v2/style-guide/#Component-name-casing-in-templates-strongly-recommended
try this working code:
App.js
<template>
<div id="app">
<FormulateInput
type="email"
name="email"
label="Enter your email address"
help="We’ll send you an email when your ice cream is ready"
validation="required|email"
/></div>
</template>
<script>
import Vue from "vue";
import VueFormulate from '#braid/vue-formulate';
Vue.use(VueFormulate);
export default {
name: "App",
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
and Main.js must be like this:
import Vue from "vue";
import App from "./App.vue";
new Vue({
render: h => h(App)
}).$mount("#app");
It actually render component but without style! if you want to use component style, write :
#import '../node_modules/#braid/vue-formulate/themes/snow/snow.scss';
in your scss style file or import https://github.com/wearebraid/vue-formulate/blob/master/dist/snow.min.css in your project!

Why is my mail being marked as spam when send via Mvc.Mailer?

I am using the Nuget Package Mvc.Mailer to send e-mail to my clients. I followed this guide and I'm encountering one really annoying thing. My sent e-mails are always sent to spam. Here's what my code looks like:
UserMailer:
public virtual MvcMailMessage Authenticatie(User user, string email)
{
ViewBag.User = user;
ViewBag.Email = email;
return Populate(x =>
{
x.Subject = "Your registration at Example";
x.ViewName = "Registration";
x.IsBodyHtml = true;
x.From = "Name <noreply#example.com>";
x.To.Add(email);
});
}
Registration.cshtml:
using Mvc.Mailer
<div>
<p style="display: none">Stuff in my email</p>
<h1 style="background: #e68425; text-align: center; color: white; margin: 0px; padding: 10px;">
A bunch of HTML
</h1>
<div style="background: #cf7721; text-align: center; padding: 10px;">
<h3 style="margin: 0px;">Activate account</h3>
</div>
<div>
<p>Dear client,</p>
<p>
Thanks for bla bla bla... And more stuff.
</p>
<table>
<tr>
<td>Login:</td>
<td>#ViewBag.User.Login</td>
</tr>
<tr>
<td>Activatiecode:</td>
<td>#ViewBag.User.Activation</td>
</tr>
</table>
</div>
Web.config:
<mailSettings>
<!-- Method#1: Configure smtp server credentials -->
<smtp from="Example <noreply##example.com>">
<network enableSsl="false" host="mail.#example.com" port="25" userName="noreply#example.com" password="xxx" />
</smtp>
</mailSettings>
What we have tried
Sending our e-mails via the standard way, with the SmtpClient. This mail didn't go to spam.
Setting x.From to a better name.
Different content types
x.IsBodyHtml = true
Sending an e-mail from our e-mail client (same address). This mail didn't go to spam.
Questions
Could our e-mail be filtered by excessive use of html?
Has anybody encountered this problem before, using this Nuget package?
How can I stop my e-mails from going to spam?
Above all: why are they going to spam?
Try to check all hyperlinks in template. It was just the word "email" in one of my Url.Action for becoming junk.

How can I check if an app is installed from a web-page on an iPhone

I want to create a web-page, a page that will redirect an iPhone to the App Store if the iPhone does not have the application installed, but if the iPhone has the app installed I want it to open the application.
I have already implemented a custom URL in the iPhone application, so I have a URL for the application that is something like:
myapp://
And if this URL is invalid, I want the page to redirect to the App Store. Is this possible at all?
If I don't have the application installed on the phone and write the myapp:// URL in Safari, all I get is an error message.
Even if there exists an ugly hack with JavaScript, I would really like to know.
As far as I know you can not, from a browser, check if an app is installed or not.
But you can try redirecting the phone to the app, and if nothing happens redirect the phone to a specified page, like this:
setTimeout(function () { window.location = "https://itunes.apple.com/appdir"; }, 25);
window.location = "appname://";
If the second line of code gives a result then the first row is never executed.
Similar questions:
iPhone browser: Checking if iPhone app is installed from browser
Is it possible to register a http+domain-based URL Scheme for iPhone apps, like YouTube and Maps?
To further the accepted answer, you sometimes need to add extra code to handle people returning to the browser after launching the app - that the setTimeout function will run whenever they do. So, I do something like this:
var now = new Date().valueOf();
setTimeout(function () {
if (new Date().valueOf() - now > 100) return;
window.location = "https://itunes.apple.com/appdir";
}, 25);
window.location = "appname://";
That way, if there has been a freeze in code execution (i.e., app switching), it won't run.
iOS Safari has a feature that allows you to add a "smart" banner to your webpage that will link either to your app, if it is installed, or to the App Store.
You do this by adding a meta tag to the page. You can even specify a detailed app URL if you want the app to do something special when it loads.
Details are at Apple's Promoting Apps with Smart App Banners page.
The mechanism has the advantages of being easy and presenting a standardized banner. The downside is that you don't have much control over the look or location. Also, all bets are off if the page is viewed in a browser other than Safari.
As of 2017, it seems there's no reliable way to detect an app is installed, and the redirection trick won't work everywhere.
For those like me who need to deep-link directly from emails (quite common), it is worth noting the following:
Sending emails with appScheme:// won't work fine because the links will be filtered in Gmail
Redirecting automatically to appScheme:// is blocked by Chrome: I suspect Chrome requires the redirection to be synchronous to user interaction (like a click)
You can now deep link without appScheme:// and it's better but it requires a modern platform and additional setup. Android iOS
It is worth noting that other people already thought about this in-depth. If you look at how Slack implements his "magic link" feature, you can notice that:
It sends an email with a regular HTTP link (ok with Gmail)
The web page has a big button that links to appScheme:// (ok with Chrome)
#Alistair pointed out in this answer that sometimes users will return to the browser after opening the app. A commenter to that answer indicated that the times values used had to be changed depending on iOS version.
When our team had to deal with this, we found that the time values for the initial timeout and telling whether we had returned to the browser had to be tuned, and often didn't work for all users and devices.
Rather than using an arbitrary time difference threshold to determine whether we had returned to the browser, it made sense to detect the "pagehide" and "pageshow" events.
I developed the following web page to help diagnose what was going on. It adds HTML diagnostics as the events unfold, mainly because using techniques like console logging, alerts, or Web Inspector, jsfiddle.net, etc. all had their drawbacks in this work flow. Rather than using a time threshold, the JavaScript counts the number of "pagehide" and "pageshow" events to see whether they have occurred. And I found that the most robust strategy was to use an initial timeout of 1000 (rather than the 25, 50, or 100 reported and suggested by others).
This can be served on a local server, e.g. python -m SimpleHTTPServer and viewed on iOS Safari.
To play with it, press either the "Open an installed app" or "App not installed" links. These links should cause respectively the Maps app or the App Store to open. You can then return to Safari to see the sequence and timing of the events.
(Note: this will work for Safari only. For other browsers (like Chrome) you'd have to install handlers for the pagehide/show-equivalent events).
Update: As #Mikko has pointed out in the comments, the pageshow/pagehide events we are using are apparently no longer supported in iOS8.
<html>
<head>
</head>
<body>
Open an installed app
<br/><br/>
App not installed
<br/>
<script>
var hideShowCount = 0 ;
window.addEventListener("pagehide", function() {
hideShowCount++;
showEventTime('pagehide');
});
window.addEventListener("pageshow", function() {
hideShowCount++;
showEventTime('pageshow');
});
function clickHandler(){
var hideShowCountAtClick = hideShowCount;
showEventTime('click');
setTimeout(function () {
showEventTime('timeout function ' + (hideShowCount-hideShowCountAtClick) + ' hide/show events');
if (hideShowCount == hideShowCountAtClick){
// app is not installed, go to App Store
window.location = 'http://itunes.apple.com/app';
}
}, 1000);
}
function currentTime()
{
return Date.now()/1000;
}
function showEventTime(event){
var time = currentTime() ;
document.body.appendChild(document.createElement('br'));
document.body.appendChild(document.createTextNode(time + ' ' + event));
}
</script>
</body>
</html>
You can check out this plugin that tries to solve the problem. It is based on the same approach as described by missemisa and Alastair etc, but uses a hidden iframe instead.
https://github.com/hampusohlsson/browser-deeplink
I needed to do something like this, and I ended up going with the following solution.
I have a specific website URL that will open a page with two buttons
Button one go to the website
Button two go to the application (iPhone / Android phone / tablet). You can fall back to a default location from here if the app is not installed (like another URL or an app store)
Cookie to remember the user's choice
<head>
<title>Mobile Router Example </title>
<script type="text/javascript">
function set_cookie(name,value)
{
// JavaScript code to write a cookie
}
function read_cookie(name) {
// JavaScript code to read a cookie
}
function goToApp(appLocation) {
setTimeout(function() {
window.location = appLocation;
// This is a fallback if the app is not installed.
// It could direct to an app store or a website
// telling user how to get the app
}, 25);
window.location = "custom-uri://AppShouldListenForThis";
}
function goToWeb(webLocation) {
window.location = webLocation;
}
if (readCookie('appLinkIgnoreWeb') == 'true' ) {
goToWeb('http://somewebsite');
}
else if (readCookie('appLinkIgnoreApp') == 'true') {
goToApp('http://fallbackLocation');
}
</script>
</head>
<body>
<div class="iphone_table_padding">
<table border="0" cellspacing="0" cellpadding="0" style="width:100%;">
<tr>
<td class="iphone_table_leftRight"> </td>
<td>
<!-- Intro -->
<span class="iphone_copy_intro">Check out our new app or go to website</span>
</td>
<td class="iphone_table_leftRight"> </td>
</tr>
<tr>
<td class="iphone_table_leftRight"> </td>
<td>
<div class="iphone_btn_padding">
<!-- Get iPhone app button -->
<table border="0" cellspacing="0" cellpadding="0" class="iphone_btn" onclick="set_cookie('appLinkIgnoreApp',document.getElementById('chkDontShow').checked);goToApp('http://getappfallback')">
<tr>
<td class="iphone_btn_on_left"> </td>
<td class="iphone_btn_on_mid">
<span class="iphone_copy_btn">
Get The Mobile Applications
</span>
</td>
<td class="iphone_btn_on_right"> </td>
</tr>
</table>
</div>
</td>
<td class="iphone_table_leftRight"> </td>
</tr>
<tr>
<td class="iphone_table_leftRight"> </td>
<td>
<div class="iphone_btn_padding">
<table border="0" cellspacing="0" cellpadding="0" class="iphone_btn" onclick="set_cookie('appLinkIgnoreWeb',document.getElementById('chkDontShow').checked);goToWeb('http://www.website.com')">
<tr>
<td class="iphone_btn_left"> </td>
<td class="iphone_btn_mid">
<span class="iphone_copy_btn">
Visit Website.com
</span>
</td>
<td class="iphone_btn_right"> </td>
</tr>
</table>
</div>
</td>
<td class="iphone_table_leftRight"> </td>
</tr>
<tr>
<td class="iphone_table_leftRight"> </td>
<td>
<div class="iphone_chk_padding">
<!-- Check box -->
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td><input type="checkbox" id="chkDontShow" /></td>
<td>
<span class="iphone_copy_chk">
<label for="chkDontShow"> Don’t show this screen again.</label>
</span>
</td>
</tr>
</table>
</div>
</td>
<td class="iphone_table_leftRight"> </td>
</tr>
</table>
</div>
</body>
</html>
After compiling a few answers, I've come up with the following code. What surprised me was that the timer does not get frozen on a PC (Chrome and Firefox) or Android Chrome - the trigger worked in the background, and the visibility check was the only reliable information.
var timestamp = new Date().getTime();
var timerDelay = 5000;
var processingBuffer = 2000;
var redirect = function(url) {
//window.location = url;
log('ts: ' + timestamp + '; redirecting to: ' + url);
}
var isPageHidden = function() {
var browserSpecificProps = {hidden:1, mozHidden:1, msHidden:1, webkitHidden:1};
for (var p in browserSpecificProps) {
if(typeof document[p] !== "undefined"){
return document[p];
}
}
return false; // Actually inconclusive, assuming not
}
var elapsedMoreTimeThanTimerSet = function(){
var elapsed = new Date().getTime() - timestamp;
log('elapsed: ' + elapsed);
return timerDelay + processingBuffer < elapsed;
}
var redirectToFallbackIfBrowserStillActive = function() {
var elapsedMore = elapsedMoreTimeThanTimerSet();
log('hidden:' + isPageHidden() + '; time: ' + elapsedMore);
if (isPageHidden() || elapsedMore) {
log('not redirecting');
}else{
redirect('appStoreUrl');
}
}
var log = function(msg){
document.getElementById('log').innerHTML += msg + "<br>";
}
setTimeout(redirectToFallbackIfBrowserStillActive, timerDelay);
redirect('nativeApp://');
JS Fiddle
The following answer still works, tested on iOS 10 through 14. It builds upon earlier answers. I added window.close() to get rid of the empty tab window that was left behind in browsers after the redirects or page return. If fixes 2 of the 4 scenarios where a blank tab would be left behind....maybe someone else can fix the 3rd & 4th
<script>
var now = new Date().valueOf();
setTimeout(function () {
// time stamp comaprison prevents redirecting to app store a 2nd time
if (new Date().valueOf() - now > 100) {
window.close() ; // scenario #4
// old way - "return" - but this would just leave a blank page in users browser
//return;
}
if (isIOS == 1) {
// still can't avoid the "invalid address" safari pops up
// but at least we can explain it to users
var msg = "'invalid address' = MyApp NOT DETECTED.\n\nREDIRECTING TO APP STORE" ;
} else {
var msg = "MyApp NOT DETECTED\n\nREDIRECTING TO APP STORE" ;
}
if (window.confirm(msg)) {
window.location = "<?=$storeUrl?>";
// scenario #2 - will leave a blank tab in browser
} else {
window.close() ; // scenario #3
}
}, 50);
window.location = "<?=$mobileUrl?>";
// scenario #1 - this will leave a blank tab
</script>
I have been trying to achieve the same in a Safari extension for iOS15. It seems that all previous strategies fail - the "Open in" dialog and the "Invalid address" one are completely equal, both non-blocking, so the timer-based solutions offer inconsistent results, depending on the time it takes to load the page.
My workaround was to create an app store redirect message within a modal popup that imitates the appearance of the system prompt, hide it behind the system prompt, and dismiss it with an event listener when the tab loses focus. There are two remaining problems with the UX:
There is no way to suppress the "Invalid address" prompt. All we can do (if we don't go the Universal Links path) is to explain it afterwards with our own prompt.
If the user chooses "Cancel" from the "Open in" prompt, he or she is still presented with our redirect prompt.
The following code benefitted both from the answers above and from this SO code for creating a modal popup.
// Change the following vars to suit your needs
var my_app_name = "My App";
var my_app_id = "id1438151717"
var my_app_scheme = "myapp://do.this"
function toggleModal(isModal, inputs, elems, msg) {
for (const input of inputs) input.disabled = isModal;
modal.style.display = isModal ? "block" : "none";
elems[0].textContent = isModal ? msg : "";
}
function myConfirm(msg) {
const inputs = [...document.querySelectorAll("input, textarea, select")].filter(input => !input.disabled);
const modal = document.getElementById("modal");
const elems = modal.children[0].children;
return new Promise((resolve) => {
toggleModal(true, inputs, elems, msg);
elems[3].onclick = () => resolve(true);
elems[4].onclick = () => resolve(false);
}).then(result => {
toggleModal(false, inputs, elems, msg);
return result;
});
}
function redirectMessage() {
var r = myConfirm("To download " + my_app_name + ", tap OK.");
return r.then(ok => {
if (ok) {
console.log("Redirecting to the App Store...");
window.location = "itms-apps://itunes.apple.com/app/" + my_app_id;
} else {
console.log("User cancelled redirect to the App Store");
}
return ok;
});
}
function prepareListener() {
document.addEventListener("visibilitychange", function() {
const inputs = [...document.querySelectorAll("input, textarea, select")].filter(input => !input.disabled);
const modal = document.getElementById("modal");
const elems = modal.children[0].children;
if (!document.hasFocus()) {
console.log("User left tab. Closing modal popup")
toggleModal(false, inputs, elems, "");
}
});
}
function onTap() {
setTimeout(function() {
// We can't avoid the "invalid address" Safari popup,
// but at least we can explain it to users.
// We will create a modal popup behind it, which the
// event listener will close automatically if the app
// opens and we leave the tab
redirectMessage()
}, 50);
window.location = my_app_scheme;
}
prepareListener()
#modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background: rgb(0, 0, 0);
background: rgba(0, 0, 0, 0.4);
font-family: "ms sans serif", arial, sans-serif;
font-size: medium;
border-radius: 15px;
}
#modal>div {
position: relative;
padding: 10px;
width: 320px;
height: 60px;
margin: 0 auto;
top: 50%;
margin-top: -45px;
background: white;
border: 2px outset;
border-radius: 15px;
}
#cancel_button {
position: fixed;
right: 50%;
margin-right: -95px;
bottom: 50%;
margin-bottom: -32px;
padding: 0;
border: none;
background: none;
color: rgb(0, 122, 255);
font-size: medium;
font-weight: normal;
}
#ok_button {
position: fixed;
right: 50%;
margin-right: -140px;
bottom: 50%;
margin-bottom: -32px;
padding: 0;
border: none;
background: none;
color: rgb(0, 122, 255);
font-size: medium;
font-weight: semi-bold;
}
<div id="modal">
<div>
<div></div><br><br>
<button id="ok_button">OK</button>
<button id="cancel_button">Cancel</button>
</div>
</div>
<p> Tap here to open app </p>
The date solution is much better than others. I had to increment the time to 50 like that.
This is a Twitter example:
// On click of your event handler...
var twMessage = "Your Message to share";
var now = new Date().valueOf();
setTimeout(function () {
if (new Date().valueOf() - now > 100)
return;
var twitterUrl = "https://twitter.com/share?text=" + twMessage;
window.open(twitterUrl, '_blank');
}, 50);
window.location = "twitter://post?message=" + twMessage;
The only problem on mobile iOS Safari is when you don't have the app installed on the device, and so Safari shows an alert that autodismisses when the new URL is opened. Anyway, it is a good solution for now!
I didn't read all of these answers, but you may be use an iframe and adding the source to, "my app://whatever".
Then check regularly on a set interval of the page is 404 or not.
You could also use an Ajax call. If there is a 404 response then the app is not installed.

Validation in HTML5. :invalid classe after submit

I'm building a form and I want to use the :invalid selector to give the "required" input fields a red border if the user presses submit without filling them, but using this makes them appear highlighted right when the page loads. It seems unfriendly to give this kind of warning to the user before even giving him the chance to fill them at least once.
Is there a way that these fields appear highlighted only after trying to submit the form, said in another way, is there a way to run the validation only after clicking submit (or at least losing focus on the required input fields?)
I used this approach for a project of mine, so the invalid fields would be highlighted only after submit:
HTML:
<form>
<input type="email" required placeholder="Email Address">
<input type="password" required placeholder="Password">
<input type="submit" value="Sign in">
</form>
CSS:
input.required:invalid {
color: red;
}
JS (jQuery):
$('[type="submit"]').on('click', function () {
// this adds 'required' class to all the required inputs under the same <form> as the submit button
$(this)
.closest('form')
.find('[required]')
.addClass('required');
});
Very simple just use #ID:invalid:focus
This only does the validation when focused on and not on page load
In addition to #Alexander Farkas' post, Dave Rupert has a very workable solution here: Happier HTML5 Form Validation.
Essentially, what it does is add a CSS class to form input elements that only displays after a user attempts to submit the form. This is much better UX, in that these elements won't show the invalid styling by default, or when a user tabs through them, which enhances accessibility.
Prior to finding this, I tried styling elements with :invalid:focus and other pseudo-elements, but didn't get the desired effect. Although I try to do my styling with pure CSS as much as possible, this looks like a use case where efficient JS is the practical solution.
No there is nothing out of the box.
Mozilla has its own pseudoclass for something very similiar called ':-moz-ui-invalid'. If you want to achieve something like this, you have to use the constraint validation DOM-API:
if(document.addEventListener){
document.addEventListener('invalid', function(e){
e.target.className += ' invalid';
}, true);
}
You can also use webshims lib polyfill, which will not only polyfill incapable browsers, but also adds something similiar like -moz-ui-invalid to all browser (.form-ui-invalid).
Another way is to add a hide-hints class to the inputs with JavaScript on load. When a user modifies a field you remove the class.
In your CSS you then apply styling to input:not(.hide-hints):invalid. This means the error styling will be shown for users without JavaScript as well.
Old question, but for people that might might find it useful: I made a little script that adds a class to a form when it's attempted to be submitted, so that you can style forms that have and haven't been attempted to be submitted differently:
window.addEventListener('load', function() {
/**
* Adds a class `_submit-attempted` to a form when it's attempted to be
* submitted.
*
* This allows us to style invalid form fields differently for forms that
* have and haven't been attemted to submit.
*/
function addFormSubmitAttemptedTriggers() {
var formEls = document.querySelectorAll('form');
for (var i = 0; i < formEls.length; i++) {
function addSubmitAttemptedTrigger(formEl) {
var submitButtonEl = formEl.querySelector('input[type=submit]');
if (submitButtonEl) {
submitButtonEl.addEventListener('click', function() {
formEl.classList.add('_submit-attempted');
});
}
}
addSubmitAttemptedTrigger(formEls[i]);
}
}
addFormSubmitAttemptedTriggers();
});
Now forms that are attempted to be submitted will get a class _submit-attempted, so you can only give these fields a red box shadow:
input {
box-shadow: none;
}
form._submit-attempted input {
box-shadow: 0 0 5px #F00;
}
You can achieve this by chaining pseudo-classes:
<style>
input:required:focus:invalid {
...
}
</style>
that way the input field will just show invalid styles only when that input field required and focused.
Here is a helpful article: https://alistapart.com/article/forward-thinking-form-validation/
Another stack overflow thread on this: https://stackoverflow.com/a/7921385/11102617
I tried this in my website:
<style id="validation"></style>
<script>
function verify() {
document.getElementById("validation").innerHTML = "input:invalid { border: 1px solid red!important;}input:valid { border: 1px solid green;}";
}
</script>
Then add onclick="verify()" to your submit button, just like this:
<input type="submit" onclick="verify()">
form.invalid {
*:invalid {
box-shadow: 0px 0px 2px 1px red;
}
}
let form = document.querySelectorAll('form')[0]
form.addEventListener('submit', function() {
if (!form.checkValidity()) {
form.classList.add('invalid')
}
})
With the above styles and javascript the form controls will only display the :invalid styles after the submit event and the checkValidity check failing. An invalid check will add the invalid class to the form and activate the styles, otherwise the form will submit as usual.
Here's another solution that only styles the inputs after a submit attempt.
HTML
<form id="sign-up-form" method="post" enctype="multipart/form-data" class="login-form sign-in-form">
<input type="text" placeholder="Name" id="full-name" name="full-name" required>
...
</form>
<script>
(() => {
const form = document.getElementById('sign-up-form');
form.noValidate = true;
form.onsubmit = function(e) {
e.preventDefault();
this.reportValidity();
if (this.checkValidity()) return this.submit();
this.classList.add('submit-attempt')
}
})()
</script>
CSS
.submit-attempt input:invalid, .submit-attempt select:invalid {
border: 1px solid red;
}
for 'required' validation
way 1 - set 'required' attribute for each element on form submit
// submit button event
$('#form-submit-btn').click(function(event) {
// set required attribute for each element
$('#elm1, #elm2').attr('required','true');
// since required attribute were not set (before this event), prevent form submission
if(!$('#form')[0].checkValidity())
return;
// submit form if form is valid
$('#form').submit();
});
way 2 - use 'data' attribute
<input type="text" data-required="1">
<script type="text/javascript">
// submit button event
$('#form-submit-btn').click(function(event) {
// set required attribute based on data attribute
$(':input[data-required]').attr('required','true');
// since required attribute were not set (before this event), prevent form submission
if(!$('#form')[0].checkValidity())
return;
// submit form if form is valid
$('#form').submit();
});
</script>
the problem with waiting for an onSubmit or "submit" event listener is that the form itself is never technically being submitted when the data from the inputs is false. What I did (in react but same principle) is to set a click listener on the submit button and then set a class like "submitted".. then apply the classes accordingly
.submitted input:invalid{
outline: 2px solid red; /* oranges! yey */
}
Expanding on previous answers: Instead of adding a class to the form to indicate whether to show the :invalid styles, you can use a hidden input. The advantage is that when the form is cleared (either by a type=reset button or through javascript), the :invalid styles automatically disappear. You could add another event handler to remove a class on reset, of course; just my preference.
Note that to do it this way you have to use an invisible checkbox rather than a hidden element and specifically change the checked property. Changing an input's value or attribute through javascript changes the default value so far as .reset() is concerned. If you don't put a name on the dummy element, it won't be posted with the form, but you can still access it through javascript via id or class.
#attemptedSubmit[value=Yes] ~ :invalid,
#attemptedSubmit[value=Yes] ~ * :invalid {
border: 1px solid red;
}
<form>
<input type="checkbox" style="display:none;" id="attemptedSubmit">
... rest of the form
<input type="text" name="text" required>
... rest of the form
<input type="submit" value="Submit" onclick="$('#attemptedSubmit').prop('checked', true)">
<input type="reset" value="Clear">
</form>

How to make submit button in line with the search fields?

I have a search field and I want my search button image to be in line with the search fields but it isn't. I have used div tags to try and move it but it always moves the search fields not just the button!
HELP!
<form action="weezyresults.php" method="post">
<input type="text" name="search" size="35" value="Job Title e.g. Assistant Manager"
style="background-color:white; border:
solid 1px #6E6E6E; height: 30px; font-size:18px;
vertical-align:9px;color:#bbb"
onfocus="if(this.value == 'Job Title e.g. Assistant Manager'){this.value = '';this.style.color='#000'}" />
<input type="text" name="searchterm" size="35" value="Location e.g. Manchester"
style="background-color:white; border:
solid 1px #6E6E6E; height: 30px; font-size:18px;
vertical-align:9px;color:#bbb"
onfocus="if(this.value == 'Location e.g. Manchester'){this.value = '';this.style.color='#000'}" />
<input type="image" src="but.tiff" alt="Submit" height="30" width="60">
</form>
Thanks!
James
It looks like it's inline to me. You possibly have a problem because your using a tiff file for that button. I'd convert that to a JPG.
If yours doesn't look like this you possibly have some other css in your project that is breaking your layout.
Use floats - eg: input { float: left } on each element, that should do the trick.
Try this out
http://jsfiddle.net/TMy6p/
I have moved your styling into an external stylesheet to tidy it up a bit and help you to avoid repeating the same style tags on elements.
basically you just need to float elements and give them widths.