So, I've written a little javascript widget. All a user has to do is paste a script tag into the page, and right below it I insert a div with all of the content the user has requested.
Many sites do similar things, such as Twitter, Delicious and even StackOverflow.
What I'm curious about is how to test this widget to make sure that it will work properly on everyone's webpage. I'm not using an iframe, so I really want to make sure that this code will work when inserted most places. I know it looks the same in all browsers.
Suggestions? Or should I just build one hundred web pages and insert my script tag and see if it works? I would hope there is an easier way than that.
Once you have confirmed that your javascript works cross-browser in a controlled environment, here are some things that might cause problems when used on an actual website:
CSS
You're using a CSS class that is already being used (for a different purpose) by the target website
You're using positioning that might interfere with the site's CSS
The elements you are using are being styled by the website's CSS (you might want to use some sort of "reset" CSS that applies only to your widget)
HTML
You're creating elements with the same id attribute as an element that already exists on the website
You're specifying a name attribute that is already being used (while name can be used for multiple elements, you may not be expecting that)
Javascript
What is the expected behaviour without Javascript enabled? If your script creates everything, is it acceptable for nothing to be present without JS?
At very basic you should make sure your widget works for following test-cases. I am sure then it will work on all web-pages -
http/https: There should not be any warning for HTTPS pages for unencrypted content.
<script> / <no-script>: What if JavaScript is disabled? Is your widget still visible?
What happens when third-party cookies are disabled? Does your widget still work?
Layout-box restrictions: When parent div element's size is less than your widget. Does your widget overflow the given size and destroys owners page?
By keeping all your Javascripts under a namespace (global object) with a very unique name, you should be pretty much OK. Also, you can simply use an anonymous function if you just want to print out something.
Similar question: How to avoid name clashes in JavaScript widgets
Related
I am working on automating a process within my business, part of which is sending an email through SalesForce. We don't have access to the SF API and the email has to be sent through salesforce in order to keep the communication searchable for the coworkers.
I need to use a template which can be selected in SalesForce, however this function does not work in IE (which our RPA solution uses) so I need to build this email from scratch.
I see two options for this:
Use the HTML to recreate the format with the right variables. This entails inserting/injecting/manipulating HTML.
Copy the format into memory/the clipboard, edit it programatically and paste it into the SF interface
This question will be about option 1. I will post an additional question with regards to the second option separately and edit this question to include that link. EDIT: Here is the link to the other question!
Now on to the question:
We use the Blue Prism RPA software suite. It has a possibility to insert javascript fragments into a website and subsequently invoke them. I was hoping that I could create a javascript fragment that recreates the template, insert it and then invoke it. I have been working on this for the past week and have hardly gotten any further.
I now am able to add basic text into the required field, but have found that to be able to use the template structure I need to use a different, HTML based, field. This field I find lives inside an iframe.
I have had zero experience with javascript prior to this week (luckily it seems similar to c# in which I do have experience) and now this iframe has me stumped. Apparently when you use Selenium or similar you can switch the driver to the new iframe but I don't have that option, it needs to be done through surface automation. Within javascript as well as the console I can not get it to target the separate document within the iframe. Apparently the iframe contents are not incorporated in that way in the bigger webpage.
So my question is this: How can I "switch focus" to the iframe using javascript? How can I then edit the iframe contents through javascript? Any help, tips etc. would be highly appreciated!
If you go to developer tools in the browser (F12 or right-click inspect) you can use the inpsect tool to get the path you are looking for. an iframe is just another window inside the window and once you have the 'base path' you can then extend further into the window from the iframe base path.
You can access frames one of two ways I know of;
document.getElementById('the frame you are looking for goes here').contentWindow.targetFunction();
and/or
window.frames[0].otherfunctions
where 0 is the Nth order of frame on the window in case there are others.
once you find that path you can interact with sub-elements on that iframe by getting the path to it from within the iframe.
some things to watch out for. frames not loading yet so make sure the frame you want is loaded and no other frame is moving it around the screen at run time. Also make sure the child frame is in the same domain, I think calling javascript has issues when going cross-domain i.e. it doesn't work (stand to be corrected there though maybe it depends on group settings)
Supply some code or the layout of the page and could give you a code example but top of my head the format will look like this
var doc = window.frames[0]
var thing = getElementById(doc.getElementByPath('maybePath')
'perform some set operations like set innerhtml to thing you desire
I noticed on youtube that replies to each comment are inside a <div id="replies">. So the same id is used for every comment reply group.
When is it a good practice to give same ids to multiple similar elements?
I know ids should be unique, that's why I'm wondering about this.
To check it, go to a youtube video, inspect and select the reply area of a comment. Optionally, Ctrl+F in inspect and search replies.
YouTube uses web components which might be the reason there are multiple of the same IDs. Web components are encapsulated chunks of HTML, javascript, and CSS that you can drop into your pages. You can read more about them here: https://www.polymer-project.org/
So my thinking of why YouTube specifically has multiple of the same ID is that the replies component itself has an ID of replies and is being targeted on a component level rather than a global.
I hope this makes sense? Even if it doesn't, try to avoid ID's that aren't unique like the others mentioned.
One of the reason YouTube can have duplicate IDs, completely invalid looking html and still get away with it, it's because they are generating dynamic content. Remember, even though it is incorrect, the browser will render it just fine. They are not using the ID to mark a unique element, but more as metadata.
Note that Youtube uses custom html tags that I assume helps them reuse code for not just the website, but also for their app.
Read more about custom elements
Update: Just wanted to show an example on how generating content through an application can help you get away with things that could otherwise be a problem.
Writing Inline css is not recommended mainly because it becomes impossible to maintain the larger the css becomes. However, you can code it in an external file during development, then compile it to be inline using an application and have none of the headaches.
See example
I am working on a simple Cordova app with about 4 page types and I am trying to think through which is the better way to handle the inner HTML templates.
Hidden HTML hard coded into the HTML files that is hidden and populated/revealed by my JS.
Using a JS template system and appending and removing from the DOM.
I feel that appending all that to the DOM for a page is inefficient when I could just update the sections that change. But perhaps an append is lightweight enough where I shouldn't worry about it.
There are a number of ways you can do it. In terms of load on the browser. That is hard to say. From your question it is hard to know what is in these pages, what are you displaying, is it live data, static html etc.
When you first plot out an app, if you are from the old class of building multiple page websites, it can be a little concerning as to how well your app/page will run with all those pages crammed in to one, and all that data plus code.
The answer is, amazingly well. If done properly in modern browsers, and for example Ipads the app will run to near native performance.
The options you have are
Map all the pages into one HTML document. Hide each page content using css display:none, flip them into view using css animation, fading or just display:block.
Use a javascript routing library to map urls to blocks of code that deal with each page, this makes mapping out your app much easier, and means that buttons can just link to your pages, like a real website. see http://projects.jga.me/routie/
Building all the page templates into one page can make it hard to code, as the page becomes enormous, consider breaking the inner content of each page into separate files, you can then give each page holder a url and use a small xhr request to load the page on-the fly, once loaded you can cache it into memory or even local-storage, depending on whether you remove it when it is closed or keep it hidden.
In my experience you can put an enormous number or nodes into one page and have very little speed drop, bear in mind if you use something like jquery and do a lot of $(".page > .page1 > .items li") your going to have a slow app.
Tips
Use element ID's everywhere document.getElementById(..) is 100's of times faster in a loop that $(...)
cache elements when you find them, if you need them later store them in a memory cache.
keep for loop inner code to a minimum.
use a decent click touch libary like http://hammerjs.github.io/ and delegate all the events of the body tag or at least on each page.
If you need to touch the server, load data, think dom first, device second server later. A good app is a responsive app, that responds to the user instantly.
I know this has been posted a while ago, but for the sake of the users I am going to add my answer.
I completely agree with MartinWebb but my answer will shed some light on the results of his options. I am currently working on a similar project. Please note that this answer pertains to cordova (previously called phonegap) specifically. My app has about 5 pages with +-20 different components (input's, div's, h1's, p's, etc.). This is what i tried and the result of each:
jQuery was my first option, mainly because it is easy to use and reduces the amount of code required to accomplish a said goal. Result: First time I tried this approach I though I would spice it up with animations and transformations. The result of this was a very unresponsive app. I removed the animation and transformation, however due to the nature of my application I required multiple dynamically added components and jQuery just wasn't up for the task.
Css display:none and visible:hidden was my next option. I used javascript's dom to display certain div's. Result: This works if your not planning on switching many div shortly after one another eg. a simple menu. It quickly became apparent that this wasn't going to work. Also this does not eliminate my need for the dom. Remember document.getElementById('menu').style.display = "none"; is still part of the dom. This as a solution, for me, is poor. There is a reason that var menu= document.createElement('div'); is part of the language. Which brings me to my last option.
Building a page 90% on javascript's dom was my last option. Logically I could not see how 600 lines of code cold trump one .innerHTML or .style.display = "block"; but it did. Result: It was by far the most responsive of all the solutions.
I'm not saying that all webpages should be coded with dom appending, but as I stated previously, for a cordova app of a few pages (<6), with a few components a javascript dom appending approach would be best. It takes longer to code, but you will be rewarded with control and efficiency. I would suggest coding the backbone of your app in html and populating and controlling with javascript's dom.
Best of luck.
The first option, <div>s with display:none; would be more efficient by a small margin, but you can get the best of both worlds by compiling your JavaScript and templates together into a single file using something like browserify or require.js.
I have a quick question. I want to create a small Scheduler widget to put on my clients websites. So if I need to make a global change to the form, I would just have to do it once.
The form will have to be unique to the website because I need to know which e-mail address to send the form to once it is submitted.
I was thinking of an iFrame I could use like this:
<iframe src="http://www.domain.com/scheduler/shop-name/"></iframe>
But I don't think that would be the best method, and I wouldn't want someone directly going to that URL.
Another option is something like this:
<script type="text/javascript">
shop_id = '114000300';
</script>
<script src="http://www.domain.com/js.widget" type="text/javascript"></script>
I'm not too sure how to execute that option yet, I'm not that experienced with Javascript but what do you guys think? What are the pros and cons of the iFrame vs Javascript?
Just wondering what the best option is, and if anyone has some tips on how to get started and any security issues I need to look out for.
Thanks!
An <iframe>
Cannot communicate its size to the parent window without additional work, which limits resizing.
Provides better isolation, as you cannot access anything on the parent page. This may be a plus from your customer's perspective.
Could be written in pure HTML, no Javascript experience necessarily required.
Has its own independent CSS styles.
Works for users who have scripting disabled.
A script
Allows you full access to the parent page
Will slow page load, as the browser will load your script before rendering the rest of the page. (At least as you have shown there, there are ways around this.)
Obviously requires some experience with Javascript.
Must share styles with the parent page. This could cause compatibility problems if your client's page uses broad-scoped style rules, such as rules for * or div.
Few more points in addition to #Dark Falcon's answer,
You have more control on the design in case of an iframe. In case of javascript widget, the client's styling might conflict with the widget's styling.
iframe is better in terms of security (cookies stored are different).
Making a JavaScript widget needs more care and expertise as you need to ensure that the other JavaScript doesn't conflict yours'. (global vars etc...)
You can use a JavaScript that writes an iframe dynamically if you want to avoid someone from going directly to the URL.
In the 1990s, there was a fashion to put Javascript code directly into <a> href attributes, like this:
Press me!
And then suddenly I stopped to see it. They were all replaced by things like:
Press me!
For a link whose sole purpose is to trigger Javascript code, and has no real href target, why is it encouraged to use the onclick property instead of the href property?
The execution context is different, to see this, try these links instead:
Press me! <!-- result: undefined -->
Press me! <!-- result: A -->
javascript: is executed in the global context, not as a method of the element, which is usually want you want. In most cases you're doing something with or in relation to the element you acted on, better to execute it in that context.
Also, it's just much cleaner, though I wouldn't use in-line script at all. Check out any framework for handling these things in a much cleaner way. Example in jQuery:
$('a').click(function() { alert(this.tagName); });
Actually, both methods are considered obsolete. Developers are instead encouraged to separate all JavaScript in an external JS file in order to separate logic and code from genuine markup
http://www.alistapart.com/articles/behavioralseparation
http://en.wikipedia.org/wiki/Unobtrusive_JavaScript
The reason for this is that it creates code that is easier to maintain and debug, and it also promotes web standards and accessibility. Think of it like this: Looking at your example, what if you had hundreds of links like that on a page and needed to change out the alert behavior for some other function using external JS references, you'd only need to change a single event binding in one JS file as opposed to copying and pasting a bunch of code over and over again or doing a find-and-replace.
Couple of reasons:
Bad code practice:
The HREF tag is to indicate that there is a hyperlink reference to another location. By using the same tag for a javascript function which is not actually taking the user anywhere is bad programming practice.
SEO problems:
I think web crawlers use the HREF tag to crawl throughout the web site & link all the connected parts. By putting in javascript, we break this functionality.
Breaks accessibility:
I think some screen readers will not be able to execute the javascript & might not know how to deal with the javascript while they expect a hyperlink. User will expect to see a link in the browser status bar on hover of the link while they will see a string like: "javascript:" which might confuse them etc.
You are still in 1990's:
The mainstream advice is to have your javascript in a seperate file & not mingle with the HTML of the page as was done in 1990's.
HTH.
I open lots of links in new tabs - only to see javascript:void(0). So you annoy me, as well as yourself (because Google will see the same thing).
Another reason (also mentioned by others) is that different languages should be separated into different documents. Why? Well,
Mixed languages aren't well supported
by most IDEs and validators.
Embedding CSS and JS into HTML pages
(or anything else for that matter)
pretty much destroys opportunities to
have the embedded language checked for correctness
statically. Sometimes, the embedding language as well.
(A PHP or ASP document isn't valid HTML.)
You don't want syntax
errors or inconsistencies to show up
only at runtime.
Another reason is to have a cleaner separation between
the kinds of things you need to
specify: HTML for content, CSS for
layout, JS usually for more layout
and look-and-feel. These don't map
one to one: you usually want to apply
layout to whole categories of
content elements (hence CSS) and look and feel as well
(hence jQuery). They may be changed at different
times that the content elements are changed (in fact
the content is often generated on the fly) and by
different people. So it makes sense to keep them in
separate documents as well.
Using the javascript: protocol affects accessibility, and also hurts how SEO friendly your page is.
Take note that HTML stands for Hypter Text something something... Hyper Text denotes text with links and references in it, which is what an anchor element <a> is used for.
When you use the javascript: 'protocol' you're misusing the anchor element. Since you're misusing the <a> element, things like the Google Bot and the Jaws Screen reader will have trouble 'understanding' your page, since they don't care much about your JS but care plenty about the Hyper Text ML, taking special note of the anchor hrefs.
It also affects the usability of your page when a user who does not have JavaScript enabled visits your page; you're breaking the expected functionality and behavior of links for those users. It will look like a link, but it won't act like a link because it uses the javascript protocol.
You might think "but how many people have JavaScript disabled nowadays?" but I like to phrase that idea more along the lines of "How many potential customers am I willing to turn away just because of a checkbox in their browser settings?"
It boils down to how href is an HTML attribute, and as such it belongs to your site's information, not its behavior. The JavaScript defines the behavior, but your never want it to interfere with the data/information. The epitome of this idea would be the external JavaScript file; not using onclick as an attribute, but instead as an event handler in your JavaScript file.
Short Answer: Inline Javascript is bad for the reasons that inline CSS is bad.
The worst problem is probably that it breaks expected functionality.
For example, as others has pointed out, open in new window/tab = dead link = annoyed/confused users.
I always try to use onclick instead, and add something to the URL-hash of the page to indicate the desired function to trigger and add a check at pageload to check the hash and trigger the function.
This way you get the same behavior for clicks, new tab/window and even bookmarked/sent links, and things don't get to wacky if JS is off.
In other words, something like this (very simplified):
For the link:
onclick = "doStuff()"
href = "#dostuff"
For the page:
onLoad = if(hash="dostuff") doStuff();
Also, as long as we're talking about deprecation and semantics, it's probably worth pointing out that '</a>' doesn't mean 'clickable' - it means 'anchor,' and implies a link to another page. So it would make sense to use that tag to switch to a different 'view' in your application, but not to perform a computation. The fact that you don't have a URL in your href attribute should be a sign that you shouldn't be using an anchor tag.
You can, alternately, assign a click event action to nearly any html element - maybe an <h1>, an <img>, or a <p> would be more appropriate? At any rate, as other people have mentioned, add another attribute (an 'id' perhaps) that javascript can use as a 'hook' (document.getElementById) to get to the element and assign an onclick. That way you can keep your content (HTML) presentation (CSS) and interactivity (JavaScript) separated. And the world won't end.
I typically have a landing page called "EnableJavascript.htm" that has a big message on it saying "Javascript must be enabled for this feature to work". And then I setup my anchor tags like this...
<a href="EnableJavascript.htm" onclick="funcName(); return false;">
This way, the anchor has a legitimate destination that will get overwritten by your Javascript functionality whenever possible. This will degrade gracefully. Although, now a days, I generally build web sites with complete functionality before I decide to sprinkle some Javascript into the mix (which all together eliminates the need for anchors like this).
Using onclick attribute directly in the markup is a whole other topic, but I would recommend an unobtrusive approach with a library like jQuery.
I think it has to do with what the user sees in the status bar. Typically applications should be built for failover in case javascript isn't enabled however this isn't always the case.
With all the spamming that is going on people are getting smarter and when an email looks 'phishy' more and more people are looking at the status bar to see where the link will actually take them.
Remember to add 'return false;' to the end of your link so the page doesn't jump to the top on the user (unless that's the behaviour you are looking for).