I made a simple bookmarklet just add "is:unread" in Gmail search bar.
javascript:
(function () {
// add "is:unread" after the query
// e.g. "from:kim-kardashian" -> "from:kim-kardashian is:unread"
document.getElementsByClassName("gb_Df")[0].value =
document.getElementsByClassName("gb_Df")[0].value.concat("is:unread");
// click search button
document.getElementsByClassName("gb_Ef gb_Qf")[0].click();
}
)();
It worked well yesterday, but It doesn't work today because of the className has changed. I assume the className of search bar is changed for each session. If this is true, is there an alternative way that adds is:unread at the end of the search query?
3rd party resources outside of the your locus of control are generally never thought of as stable. This is why we have labeled versions (e.g., dev = always in flux) and contracts to try and approach stability.
For something like this HTML is generally more stable than class names, but would never say this plugin is stable while the use case is unsupported by Google.
So if indeed, what is stated is true, that the CSS class names change per session, could select from the DOM based on HTML structure or another attribute that is not hashed.
Just took a look at gmail and indeed gb_Df class name is the search bar. Guess is your account has been automagically opted into a an AB test of one gmail version to another which has generated different class name hashes.
In this scenario would choose placeholder. So something like:
document.querySelector('[placeholder="Search mail"]')
Based on experience (completely anecdotal), is very unlikely this value will change and there is currently one on the page. Could check other reasonably stable attributes to be sure you've the right one. Just keep in mind plugin hacks like this are unstable, can only incrementally increase stability by using more stable selectors, because the ground they rely on (Gmail DOM) is moving at the pace of Google. Good luck :)
Related
I have recently inherited a web app using the EXTjs framework. I'm not really that familiar with it, but I have been learning it the best I can over the last few months. I have recently been given an assignment to update the entire application to comply with 508 Compliance, that is to say, make the application accessible for those with vision issues. I was given a deficiency list that gives examples where the software doesn't comply for various reasons. I guess I need a little help in understanding how this works. I've looked at the EXTjs documentation and it does say that it has accessibility features available in it, but I haven't really been successful in finding what to do. Those using the application are using the JAWS screen reader if that makes any difference.
A few of the things I know that I need to fix are:
Some elements need to be tagged as a heading so the screen reader can read it programmatically an to give the web page some structure.
When tabbing around a table/grid the data is read without any context/header information.
Color is used as a visual cue to indicate action(ie required field). I'm supposing this is for color blindness and some other visual cue needs to be added.
Modal windows can't be resized or moved by the keyboard.
Needs a mechanism to bypass blocks of content that are repeated on multiple pages.
Pages do not have titles(this is a single page app).
Keyboard operable UI elements do not have a visible indication of focus(radio button group doesn't show focus, even if selected one does).
Name/State of UI elements in the product can't be understood(ie the name of expand and collapse buttons are read as expand panel or collapse panel by assistive tech without context to what is being expanded or collapsed).
There are many other issues, but this gives some idea of the scope of the changes required. As I have stated above, I've done a lot of examination of the EXTjs documentation at their site as well as google searches on how to make applications more accessible. But I'm not really seeing what I need. Much of this application is just configuring EXTjs templates and then loading them with much of the meat of the application being handled by the EXTjs built in js code.
I would appreciate any help, useful sites with examples, or code snippets on how to accomplish some of this. I'm hoping that once I get started with some examples, I can just go on from there.
Thanks.
Most items come with aria support. Personally I would add look into each component and add an automated aria support. E.g. button ==> aria.label = button.text
Take a look at ariaAttributes, ariaDescribedBy, ariaLabel and ariaLabelledBy. Some have ariaErrorText, ariaHelp.
Next take a look at tabIndex. You want to ensure that you can use TAB to jump through the fields, buttons, ...
Usually, we use a theme which was provided stripe like the following.
style: {
paymentRequestButton: {
theme: "light-outline"
}
}
They have also provided some theme's like 'dark' | 'light' | 'light-outline'
My question is can we create a custom theme for this button.? eg: a blue colour theme
Or is there any workaround or script hack for changing the color of the button.?
It is not possible to custom style the payment request button. However, you can use Stripe's payment request API with a custom button. The documentation only hints at this. Also, this should still be 100% PCI-compliant, as your application still never sees or touches any credit card information. I have a CodePen you can refer to as an example.
Essentially, just create whatever kind of button you want on your page. Then, bind the click event to paymentRequest.show, where paymentRequest is an instance of Stripe's PaymentRequest. For example:
let stripe = Stripe('pk_test_abc123');
let paymentRequest = stripe.paymentRequest({
...
});
let button = document.getElementById('awesome-custom-button');
button.addEventListener('click', paymentRequest.show);
Then, when you get the token, simply call ev.complete('success') before the end of the delegate function. For example:
paymentRequest.on('token', function (ev) {
// do whatever with the token
ev.complete('success');
});
The only slight hangup is that Apple dictates that the Apple Pay button must be styled a certain way, according to their HIG. The Stripe Elements payment request button handles this out of the box, but since you're no longer using the Elements button with this approach, you simply need to change your custom button manually. There's a number of ways you can do that. In my example code, I'm using Bootstrap and Fontawesome, so in the canMakePayment delegate function:
if (result.applePay) {
button.className = 'btn btn-dark';
button.style.backgroundColor = '#000';
button.querySelector('.default').style.display = 'none';
button.querySelector('.applepay').style.display = 'inline';
}
In my button HTML, I have a span with a "default" class that contains the normal button content and another span with an "applepay" class that is hidden initially and contains the following HTML:
<span class="fa-lg">
<i class="fab fa-apple-pay" data-fa-transform="grow-12"></i>
</span>
<span class="sr-only">Purchase with Apple Pay</span>
I've been trying to do this as well, but the reference docs here at the very bottom seem to indicate the answer is "no".
Looks like beyond a type, and theme the only thing you can set is a height: https://stripe.com/docs/stripe-js/reference#element-options
(Screenshot of relevant section below, in case it changes)
Reading Step 3 of Payment Request Button implementation steps, it is obvious the element has id: #payment-request-button.
Haven't worked with Stripe and I don't know if it's a <button> or a more complex HTML markup structure and I also read somewhere in their docs they do not guarantee maintaining the HTML structure of their elements.
Anyway, here are a few things to keep in mind when aiming this type of intervention: most importantly, develop in steps:
Find a solution that works for the time being. Ideally, it should be something that degrades/fails gracefully and silently (no public facing errors)
Maximize ability to withstand minor modifications in markup from Stripe
Also, keep your source files so you can easily adapt your solution to any markup breaking changes from Stripe so you can provide a fix when it stops working.
If you rely on CSS (recommended), you should inspect the currently rendered markup and find out what are the currently applying selectors. Simply writing stronger selectors should be enough. If styles are being applied via JavaScript by Stripe, chances are you will need to use !important in your CSS. Of course, you should avoid it as much as possible, or at least thoroughly test on as many devices as you can get your hands on.
As a rule of thumb, !important is quite bad in CSS. It's a very powerful hammer and most times it breaks delicate things (i.e.: responsiveness on touch devices).
Alternatively, if you rely on JavaScript to do the styling, you might want to play around with setTimeout() and determine the proper amount of miliseconds to wait before triggering your changes after the prButton.mount() method was called. Test on multiple devices. I advise against this method as it's more error prone and more difficult to control: you want to time your changes just after the element was built but (ideally) before it gets rendered. Of course, there are workarounds, such as hide or fade it until your changes are applied.
Note: This is not an easy task and nobody (except Stripe themselves, by providing a proper method) can guarantee you a bullet-proof solution so I thought laying out the principles on how to approach it might have more value on short and long term than trying to get Stripe working on a test/dev account and provide a particular solution which might stop working the next day, when Stripe change their markup.
If there is an element like this:
var c = document.createElement('a');
Then one can add the attribute name simply by doing:
c.name = "a1";
What is the purpose of setAttribute() if one can just use the dot notation?
An attribute is not the same thing as a property.
Attributes are usually created in your HTML, and will become an object member of element.attributes. Some will also set a corresponding property.
There are some attributes that update when you change the property, but others that do not. For example, the .value property will not change the attribute on input elements. Or custom properties do not become custom attributes.
Most of the time you probably want to set the property, but if you want to change the attribute, then in some cases you must use setAttribute
Who says you can do either?
Well, okay you can. But seriously, "who says?", because it mostly comes down to that.
In the beginning, there was Netscape Navigator 2, the first web browser to support Javascript, and indeed being a few months prior to server-side use in Netscape Enterprise Server, the first anything to support Javascript (called "Livescript" in a beta version but quickly renamed "Javascript" because it was 1995 and putting the word "java" in anything was a sure-fire way to get about 20,000 column-inches out of tech journalists who spent the rest of their time wondering confused around coffee wholesalers wondering where the press releases and promotional schwag was).
The object model at the time was pretty small, to the point that you could learn it to the point where you could hold the entire model in your head in a couple of days. For most elements, you couldn't actually do very much with them. A lot of things were quite fiddly (where you can find the current value of a <select id="selId" name="selName"> today with document.getElementById('selId').value and a few other ways, then you would need document.forms[0]["selName"].options[document.forms[0]["selName"].selectedIndex].value.
Then IE3 came out with Javascript too, NN 3 upped the ante by letting you change an image's src attribute. The browser wars had begun in earnest. Many veterans are still haunted by the memories of what they did.
The really obvious way to make a browser's document model better, was to have more and more things reflected by properties - preferably writable rather than read-only. The next-best thing was to have a slightly simpler and easier to remember way of changing something than the other browser (then they might make more web pages that worked in the latest version of your browser and didn't in your rival's).
Through keeping up a rapid pace of development, it was clear that Netscape would develop a new middleware platform that would make the position of Microsoft and Apple irrelevant, while the jury was out on whether yahoo or alta-vista had the approach to search and/or directory that would dominate the web. (Don't make long-term predictions about technology).
During the general trend of make-script-able-to-do-everything-to-everything, a lot of properties got named after the corresponding attribute when there was one, which is after all a pretty sensible way.
This is a bit inconsistent though. For one thing, most properties that correspond to attributes map string values to string values in a straight-forward way. One or two do not, such as the href attribute on anchor elements which gives you a richer object with properties reflecting parts of the URI (mostly because it was available from the early days before make-script-able-to-do-everything-to-everything). Which is both useful (if you want to break the URI down) and a nuisance because there's no good way of telling which is which.
At the height of this, they had something called DHTML, and something called dHTML, which were two ways to do pretty much the same thing in completely incompatible ways.
There's also the fact that javascript is loose in letting you add a new property to anything, and HTML lets you add in new attributes (debatable, depending on how strictly you stay to which standard, but this was the browser wars and new proprietary attributes were seemingly added by one browser or another every 4 minutes). Knowing whether a property would have any real effect on any given browser was a nuisance.
Meanwhile, in a distant International Standards Consortium, something called XML was being developed. It let you add all sorts of elements with all sorts of attributes in all sorts of ways. Ways of dealing with this in script were also added.
We needed a way to more consistently change the attributes of elements than that currently existing, and since it was obvious that all future versions of HTML would be XML applications (Don't make long-term predictions about technology) it made sense for it to be at least relatively consistent between the two.
It was also dawning on everyone, that having a more popular browser than everyone else wasn't going to turn anyone into the next Bill Gates (not even the current Bill Gates) so the advantages of having greater support for standard approaches rather than greater flashy-stuff-the-other-guy-can't-do became more apparent.
The W3C DOM became more and more finalised and more and more supported. It gave us a more consistent way of setting attributes. It was more verbose, but you could know consistently what it was going to do, and it was also more powerful in creating, copying, changing and deleting parts of a document.
But old sites had to be kept going if possible, along with the fact that it does remain a useful shorthand for a lot of attributes to just set the corresponding property, so people weren't going to stop using it. Still, the DOM approach is supported to some extent by all browsers, giving much more consistency between them.
And then half the developers started using JQuery anyway.
This is to make some custom attribute:
while its all fine to make el.name='aaa';
if you make el.customsttr='a' it will not work.
-- (unless it has been already defined, as pointed out below)
http://jsfiddle.net/sXdHB/
Application:
For example you have an img, with attr 'src', then you might want to add a custom atribute 'big_src' and then read it through some script to display a bigger one;
I'd use getAttribute/setAttribute to make it clear that you're working with DOM elements. Minimizing ambiguity is a plus!
However, this is what quirksmode.org has to say about atrributes:
Attributes
A bloody mess. Try influencing attributes in this order:
Try getting or setting a specific property, like x.id or y.onclick.
If there is no specific property, use getAttribute() or
setAttribute().
If even that doesn't work, try any other method or
property in the table below. Most have horrible browser
incompatibility patterns, though.
Avoid attributes[]. It's worse
than anything else.
I have a question about Javascript widgets. The widget I am working on simply embeds content on a page instead of using iframes. So far it looks good. But there are cases where some users layouts are messing up the widget. For example, the widget might require a width of 300px to appear. But the parent div is set to 250px and hence the right part of the widget is cut off.
I was wondering what sort of precautions should be taken to prevent this? I was talking to the product manager who mentioned he wanted me to check the parent div elements and get the size and then show an alternate message if their size is not accurate. But again, since this is Javascript and the widget is supported in many diff browsers(including IE6), I am wondering how fail-safe this method would be? What if I need to iterate the DOM all the way up before getting a valid size? I am also worried about performance here. This extra checks would slow down the delivery of my widget content to "good users" since I am adding a layer of complexity to all users. I don't want to penalize good users just because of the few errant ones.
I am not using any sort of JS library here, so any solution should not suggest the use of one. Also, the reason for not using a library was simply not to add extra weight to the page load to deliver a widget. I understand that "jquery" for example is small, but in my case, even 24k compressed seems like an overkill for a widget delivery that contains no core code for the widget.
Has anyone dealt with such issues before? What are your solutions to these?
There are reliable ways of determining the size of an element using JavaScript. You're quite right that you may need to iterate up the tree in some cases, but the answer you get will ultimately be quite valid.
Although you don't want to directly include any library code in this project, you may consider looking at how the major libraries implement their "what's the width of this element" functions to drive your own implementation.
Beware of quirks mode too.
I'd check to see of the page has Jquery, if not load it into the page using no-conflict mode. Then use jQuery to examine the page.
See: How to embed Javascript widget that depends on jQuery into an unknown environment
One of my clients wants to distribute a javascript widget that people can put on their websites. However he wants to ensure that the backlink is left intact (for SEO purposes and part of the price of using the widget). So the javascript he's going to distribute might look like this:
<script id="my-script" src="http://example.com/widget-script.js"></script>
<div style='font-size:10px'><a href='http://www.example.com/backlinkpage.html'>
Visit Exaxmple.com</a></div>
widget-script.js would display some html on the page. But what wew want to ensure is that some wiley webmaster doesn't strip out the back link. If they do we might display a message like "widget installed incorrectly" or something. Any ideas / thoughts.
Some code taken from this question.
There's no 100% way of preventing this, I'm afraid.
You could insert the link yourself with Javascript, but then it'd be for naught as far as PageRank goes.
You could give them the HTML with the link having an ID like mycompanybacklink and check with Javascript whether the element exists or not. If it doesn't, don't display the badge or whatever. If it does, you can verify that the link's href is your website and its text is what you want. You would have to edit the HTML you posted as sample so that the link comes before the script, not after. The element could still exist, however, but be blocked by some other element or simply hidden with CSS. You could then also do something akin to what jQuery does now with its :hidden selector: Instead of looking at the CSS property by itself (which is what a webmaster is most likely to try) you can just see whether the element itself or its parents take up any space in the document. I think this is done with offsetWidth and offsetHeight but I am not sure. Worth looking into, though....
If you wanted to ensure that the link is always there with the widget, you could just have it printed via JavaScript. However, I don't think search engines would pick it up as a backlink.
I think you're just going to have to trust that your users will act in good faith and show you the courtesy of not modifying/removing the link. You also need to accept that no matter what you do, a determined webmaster will be able to use your widget without displaying the link, and some inevitably won't, but they are likely to be in the minority (unless your backlink is just really intrusive or obnoxiously distracting).
Any JavaScript/HTML solution could simply be edited out by the webmaster. You'd have to make your widget in flash if you really want to prevent tampering.