I use Slack, and one think we love to do is share new articles and discuss them. But the good old copy and past the link was annoying me, so I created a Bookmarklet that will share your current page to a selected channel.
This is my personal blog and mainly contains technical solutions, open source code, and other projects I have worked on. Much of the technical solutions are very niche so your milage may vary.
Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts
Friday, December 4, 2015
Thursday, October 8, 2015
Making Time Based Graphs with Chartist
I have been implementing some custom charts with Chartist recently. Overall things have gone very well with some simple tweaks and fiddling to get things exactly how I want. It is very nice to be be able to easily adjust the charts with CSS right in the normal site code.
Friday, July 31, 2015
Drag and Drop in Umbraco 7
This code will let you add drag and drop logic to Umbraco v7 using the new AngularJS interface. It doesn't require and backend code updates but can't be created as a package because there is no way to update the umbTree directive as needed. There are only two files that need to be changed on the client. Note that updates to umbraco will overwrite these changes. Also note that due to lack of support in the underlying jQuery-sortable plugin for touch events this will not work on tablet devices.
First a set of changes for the umbTree and umbTreeItem directives in umbraco/Js/umbraco.directives.js.
This patch was generated on 7.2.8 so may not work on other versions automatically. You can manually apply all the listed changes on any 7.* version and they should work as expected with no changes needed.
Secondly, to allow for dragging items to collapsed nodes or nodes they don't already have children, the following needs to be added to the end of the line in umbraco/assets/css/umbraco.css.
First a set of changes for the umbTree and umbTreeItem directives in umbraco/Js/umbraco.directives.js.
This patch was generated on 7.2.8 so may not work on other versions automatically. You can manually apply all the listed changes on any 7.* version and they should work as expected with no changes needed.
Secondly, to allow for dragging items to collapsed nodes or nodes they don't already have children, the following needs to be added to the end of the line in umbraco/assets/css/umbraco.css.
Thursday, January 29, 2015
jQuery .ensure() Function to Wait for a Condition Before Executing Code
Overview
This is a very nice little plugin I wrote for jQuery to handle situations that don't have callbacks. You can do this manually in code by adding a timeout but what if the function takes to long, or what make users with a faster device wait for slower devices by over estimating the timeout.Please note that most libraries have their own callbacks and jQuery had a
$().done() mechanism that will do this for common functions and libraries. This solution is for those odd ball code bits that don't or that you don't have control over.It takes a few pieces of information:
selector- The root jQuery selector you are binding to, it will become the this in the isValid call.
- If your waiting for a new item to be created do
$(document).ensure(selector).done(). isValid(default$(this).exists())- This is the function that is run each iteration.
- It should be optimized and return a bool result. Ie don't walk the DOM every time, select the proper parent node into a variable or pass as the selector.
delay(default500milliseconds)- Miliseconds between each iteration.
tries(default0)- Maximum number of times to try,
0for unlimited.
Examples:
Source Code:
Tuesday, March 12, 2013
Javascript function to decode HTML escape sequences.
I found a few samples that will decode the escape sequences in the following html string but none quite took my fancy. (Not to be confused with unescape witch will decode URL escape sequences.)
Here is the version I wrote:
Here is the version I wrote:
Thursday, January 31, 2013
jQuery Vertical Totem Ticker Plugin - Updated
I found this nice jQuery plugin Totem Animated Vertical Ticker. but it doesn't seam to have some options I needed. As it does not appear to be to active I made some customizations myself to add the following options.
- Added support for mouse whee scrolling.
- Tickers now all get the vTicker class for css markup.
- If a row height is specified that the items are now actually restricted to that height. Add the following css to make longer items scroll properly.
- Added helper methods for easy scripting of the ticker.
The new version is available on GitHub at https://github.com/pynej/totem.
- Added support for mouse whee scrolling.
- Tickers now all get the vTicker class for css markup.
- If a row height is specified that the items are now actually restricted to that height. Add the following css to make longer items scroll properly.
.vTicker li { overflow: hidden; }
- Added helper methods for easy scripting of the ticker.
$(selector).totemticker("start");
$(selector).totemticker("stop");
$(selector).totemticker("previous");
$(selector).totemticker("next");
The new version is available on GitHub at https://github.com/pynej/totem.
Monday, October 1, 2012
Automatic Unobtrusive Binding of Labels to Form Elements
One commonly forgotten feaure in HTML is that when creating web forms the labels related to input elements should be related to them. In the simplest terms it is done like so:
Thus I have the following bit of javascript to automatically do the same thing. It looks for any unbound labels and binds them to the next input, text area, or select item down the DOM tree from them. That is the next matching element within the same parent that the label is in. This method will also work if the input fields don't have ID's associated with them as an added bonus.
To use just include this in a global script running on your site and it will do the work with no noticeable overhead. This does require jQuery to work.
<label for="myItem">My Label</label><input id="myItem">
The benifit to doing this is that browser will automatically focus the input element when the label is selected. A little thing I know but it's not use in most sites doe to inconvenience.Thus I have the following bit of javascript to automatically do the same thing. It looks for any unbound labels and binds them to the next input, text area, or select item down the DOM tree from them. That is the next matching element within the same parent that the label is in. This method will also work if the input fields don't have ID's associated with them as an added bonus.
To use just include this in a global script running on your site and it will do the work with no noticeable overhead. This does require jQuery to work.
$(document).ready(function () {
$("form label").each(function() {
if (typeof $(this).attr("for") == "undefined" || $("#" + $(this).attr("for")).length == 0) {
nextControl = $(this).next("input,textarea,select");
if (nextControl.length > 0) {
if (typeof nextControl.attr("id") != "undefined") {
$(this).attr("for", nextControl.attr("id"));
} else {
$(this).removeAttr("for");
$(this).click(function() {
$(this).next("input,textarea,select").focus()
});
}
}
}
});
});
Tuesday, July 24, 2012
jQuery Plugin to Scroll an Element with the Page
Updated 11/7/2013: Added support for positioning via padding instead of margins.
This simple javascript plugin is a very simple bit of code that can be attached to any element on a web page. It will make the element work similar of a position:fixed element in that it will cause the element to scroll with the browser window vertically as the user scrolls up and down.
The benefit of this over the css attribute is that this method will retain the items original placement and flow instead simply adjust the margin-top to replicate the scrolling logic. Additional paddingTop and paddingBottom can be specified witch will act as minimum margins between the viewport and the floating item.
Sample Code:
The query Plugin code is available on GitHub here. You will need to include jQuery and then this file in your page header to use it.
This simple javascript plugin is a very simple bit of code that can be attached to any element on a web page. It will make the element work similar of a position:fixed element in that it will cause the element to scroll with the browser window vertically as the user scrolls up and down.
The benefit of this over the css attribute is that this method will retain the items original placement and flow instead simply adjust the margin-top to replicate the scrolling logic. Additional paddingTop and paddingBottom can be specified witch will act as minimum margins between the viewport and the floating item.
Sample Code:
$("#element").autoScroll({ paddingTop: 30 });
The query Plugin code is available on GitHub here. You will need to include jQuery and then this file in your page header to use it.
Friday, July 6, 2012
Web Form Validation the Right/Simple Way.
Another topic that isn't all all new. There are millions of forms out there and they all do user input validation differently. The long and the short of this article is that there are many approaches but we want a best practice that meets a few requirements. It must be quick, efficient, simple to configure, but able to do all the validation logic we may need. There are lots of frameworks or custom code to do this but as I mentioned I am going for the most elegant solution here. So here is goes, here is a sample form with the validation logic.
This might look quite impel but in reality is is doing nearly all the validation we need for this simple form. I am using the jQuery Validation plugin to do all the heavy lifting here. This is also a very elegant solution. You will notice that there is only one javascript call on the page yet all the fields are being validated. How you ask? While the documentation doesn't covert it very well but jquery.validation will acutely use the css class markup to apply validation rules. See the form controls that have the classes required, email, phoneUS, and zip. These are what trigger the validation logic. In essence this is the same to the following script tag but this little know markup is much cleaner.
Now you can see why the css markup trick is a lot cleaner. It also keeps the rules along with the fields they are affecting to it is easier to track down problems with the validation.
On another point you may notice that the first sample I posted is not validating the phone number and zip code properly. That is because I created custom class rules and methods that are not in the validation framework. The following class rule, think alias or marco, and method need to be added to the script tag after the validation include or more simply just added to a site wide script file. The first is a macro that applies multiple rules as a set. This also allows you to apply rules with parameters witch you can't do in the css markup. The second is an entirely new method that does some complex regular expression validation.
This approve can now be used to add as complex of validation logic as needed. The user will automatically see nice callouts when they try to submit the form with errors on it. Also of note this solution will fail gracefully so if there is a script error or javacscript is just unavailable the page will still function and post to the server. Now with that in mind it brings me to my final point. The receiving server side script should always to its own validation to catch not only these rare cases where javacript is disabled or some other error occurred, but also to catch cases there some user is intentionally trying to submit invalid data. And clint side validation like this can easily be disabled but the end user and a invalid form submitted. Thus the onus is always on the server code/database for true validation.
<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.2.min.js'></script>
<script type='text/javascript' src='http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.js'></script>
<script type='text/javascript'>
$(document).ready(function() {
$("#myForm").validate();
}
</script>
<form action='?' method='post' id='myForm'>
<p>
<label for='firstName'>First Name:</label> <input name='firstName' id='firstName' class='required' type='text'>
</p>
<p>
<label for='lastName'>Last Name:</label> <input name='lastName' id='lastName' class='required' type='text'>
</p>
<p>
<label for="custType">Type:</label> <select name="custType" id="custType" class='required'>
<option value=""></option>
<option value="vendor">Vendor</option>
<option value="salesrep">Sales Rep</option>
<option value="supplier">Supplier</option>
<select>
</p>
<p>
<label for='emailAddress'>Email Address:</label> <input name='emailAddress' id='emailAddress' class='required email' type='text'>
</p>
<p>
<label for='primaryPhone'>Phone Number:</label> <input name='primaryPhone' id='primaryPhone' class='required phoneUS' type='text'>
</p>
<p>
<label for='zipCode'>Zip Code:</label> <input name='zipCode' id='zipCode' class='required zip' type='text'>
</p>
<p>
<input type='submit' name='save' id='save' value='Save'>
</p>
</form>
This might look quite impel but in reality is is doing nearly all the validation we need for this simple form. I am using the jQuery Validation plugin to do all the heavy lifting here. This is also a very elegant solution. You will notice that there is only one javascript call on the page yet all the fields are being validated. How you ask? While the documentation doesn't covert it very well but jquery.validation will acutely use the css class markup to apply validation rules. See the form controls that have the classes required, email, phoneUS, and zip. These are what trigger the validation logic. In essence this is the same to the following script tag but this little know markup is much cleaner.
$("#myForm").validate({
rules: {
firstName: "required",
lastName: "required",
custType: "required",
emailAddress: {
required: true,
email: true
},
primaryPhone: {
required: true,
phoneUS: true
},
zipCode: {
required: true,
digits: true,
minlength: 5,
maxlength: 5
}
}
})
Now you can see why the css markup trick is a lot cleaner. It also keeps the rules along with the fields they are affecting to it is easier to track down problems with the validation.
On another point you may notice that the first sample I posted is not validating the phone number and zip code properly. That is because I created custom class rules and methods that are not in the validation framework. The following class rule, think alias or marco, and method need to be added to the script tag after the validation include or more simply just added to a site wide script file. The first is a macro that applies multiple rules as a set. This also allows you to apply rules with parameters witch you can't do in the css markup. The second is an entirely new method that does some complex regular expression validation.
jQuery.validator.addClassRules({
zip: {
digits: true,
minlength: 5,
maxlength: 5
}
});
jQuery.validator.addMethod("phoneUS", function(phone_number, element) {
phone_number = phone_number.replace(/\s+/g, "");
return this.optional(element) || phone_number.length > 9 &&
phone_number.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/);
}, "Please specify a valid phone number");
This approve can now be used to add as complex of validation logic as needed. The user will automatically see nice callouts when they try to submit the form with errors on it. Also of note this solution will fail gracefully so if there is a script error or javacscript is just unavailable the page will still function and post to the server. Now with that in mind it brings me to my final point. The receiving server side script should always to its own validation to catch not only these rare cases where javacript is disabled or some other error occurred, but also to catch cases there some user is intentionally trying to submit invalid data. And clint side validation like this can easily be disabled but the end user and a invalid form submitted. Thus the onus is always on the server code/database for true validation.
Friday, June 29, 2012
Show prompt/Run script when navigating away from a web page.
In the world of web browsers there are some real limitations to responding to user actions. Specifically when a user is viewing a web page they can navigate away from said page in a few different ways and it can be tricky to deal with and respond to these events. This is not a new topic but I have found the details online to be somewhat lacking.
A user can leave a page in many different ways. First of all they can simply click a web page link to another internal or external URL. This is the simplest action and it triggers a click event which can be responded to with a script and even canceled entirely. The following for example will show a message when the user click an external link(indicated by the presence of the class "external").
But how can we react to other types of navigation such as the browser back and forward buttons, page reload, url change, and page close events. This can be done to a limited extent with the onbeforeunload event though we can't actually see what action the user preformed to leave the page. There is a further problem here though. Simply adding a event handler on the onbeforeunload will also run when the user clicks links inside the site witch we may not want. With that in mind the following code will attach a event handler to the onbeforeunload but will discard it when it detects that a internal or external link was clicked witch can be captured normally. Additinal link level logic can then be added to the link click events.
This bit of code will allow for a script to run when the user tries to leave the page and can warn about unsaved changes, etc. Be warned though that this is only a prompt and furthermore that in most cases this type of alert/warning to users may be irritating. It should only be used to trigger warnings about unsaved changes, etc. Also there are some other limits here. For example you can't redirect the browser to a new url on page exit as the browser is already changing pages.
A user can leave a page in many different ways. First of all they can simply click a web page link to another internal or external URL. This is the simplest action and it triggers a click event which can be responded to with a script and even canceled entirely. The following for example will show a message when the user click an external link(indicated by the presence of the class "external").
$(document).ready(function()
$("a.external").click(function() {
alert("Leaving to " + $(this).attr("herf"));
});
});
But how can we react to other types of navigation such as the browser back and forward buttons, page reload, url change, and page close events. This can be done to a limited extent with the onbeforeunload event though we can't actually see what action the user preformed to leave the page. There is a further problem here though. Simply adding a event handler on the onbeforeunload will also run when the user clicks links inside the site witch we may not want. With that in mind the following code will attach a event handler to the onbeforeunload but will discard it when it detects that a internal or external link was clicked witch can be captured normally. Additinal link level logic can then be added to the link click events.
$(document).ready(function() {
// Listen for the unload event and return a warning/run custom code.
window.onbeforeunload = function (event) {
if(true) {
return "You have items in your cart.";
}
}
// If disable event on link clicks that are not hash links, mailto, or javascript calls.
$("a[href]:not([href^=#],[href^=mailto],[href^=javascript])").click(function(){
window.onbeforeunload = null;
});
});
This bit of code will allow for a script to run when the user tries to leave the page and can warn about unsaved changes, etc. Be warned though that this is only a prompt and furthermore that in most cases this type of alert/warning to users may be irritating. It should only be used to trigger warnings about unsaved changes, etc. Also there are some other limits here. For example you can't redirect the browser to a new url on page exit as the browser is already changing pages.
Monday, June 25, 2012
Cleanly replace links with jQuery UI Dialogs.
This but of code along with a bit of link decoration will automatically open all specified links in dialog popup windows instead of in new browser windows. It benefit here is that this code is quite small, clean, and automatically applied to all matched elements on the page without having to write custom code or hooks for each link.
First of all make sure that you are including jQuery, jQuery UI and a jQuery UI Stylesheet.
Next add the following code to a external javascript file that is included on this page or into the page code itself. Not that this needs to be included/executed after the above scripts are included.
ConfigureDialogPopups.js
The final step is to go through the page and decorate and links you want to open in dialog popups with the popup attribute. This should be added directly to the A link that will trigger the popup and the href will be be the location to retrieve and place into the popup. The value of the popup attribute needs to be assigned a unique id that will be assigned to the resulting dialog object.
For example the following link can be make up as so to change it from a normal page link to a popup dialog.
Furthermore the dialog can be accessed and manipulated as needed with the following jQuery selector.
First of all make sure that you are including jQuery, jQuery UI and a jQuery UI Stylesheet.
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="http://code.jquery.com/ui/1.8.21/jquery-ui.min.js"></script>
<link href="http://code.jquery.com/ui/1.8.21/themes/base/jquery-ui.css" rel="stylesheet"></link>
Next add the following code to a external javascript file that is included on this page or into the page code itself. Not that this needs to be included/executed after the above scripts are included.
ConfigureDialogPopups.js
// make sure the page is fully loaded. $(document).ready(function() { // For each link makred up with the popup attribute change the link to open the contents in a jquery dialog instead. $("a[popup]").each(function() { $(this).click(function() {dest = $(this).attr("popup");// Get the page contents with a background ajax query. $.get($(this).attr("href"), function(data) {// Push the results into a div tag with a custom id to spit out the script and style elements. $("<div id='"+dest+"' class='"+dest+"'>" + data + "</div>").each(function() { if($(this).is("div")) {// Add the div to the page as a popup. $(this).dialog({ close: function() { $(this).remove(); }, modal: true, resizable: false }); // Move the first p to the dialog title. $("#"+dest).dialog( "option", "title", $("#"+dest+">p").first().html() ); $("#"+dest+">p").first().remove(); // Update the style of the header. $("span.ui-dialog-title").addClass("subhead14"); } else {// Add all other elements to the body directly. $(this).appendTo("body"); } }); }); // Return false so the link isn't clicked. return false; }); }); });
The final step is to go through the page and decorate and links you want to open in dialog popups with the popup attribute. This should be added directly to the A link that will trigger the popup and the href will be be the location to retrieve and place into the popup. The value of the popup attribute needs to be assigned a unique id that will be assigned to the resulting dialog object.
For example the following link can be make up as so to change it from a normal page link to a popup dialog.
<a href="page2.hmtl">View Page 2</a>
<a popup="page2dialog" href="page2.hmtl">View Page 2 (Popup)</a>
Furthermore the dialog can be accessed and manipulated as needed with the following jQuery selector.
$("#page2dialog")
Friday, April 15, 2011
Reading .NET JSON Date's in jQuery
ASP.Net writes out date objects to a JSON stream in the format { "\/Date(x)\/" } but jQuery will not automatically convert this to a JavaScript date but rather keeps it as a string. To fix that this simple converter script can be included in your global JavaScript header.
Note that this does requite jQuery 1.5+.
Note that this does requite jQuery 1.5+.
$.ajaxSetup({
// Add a custom converter to convert ASP.NET JSON dates to JS Date object
// That is convert { "\/Date(...)\/" } to { new Date(...) }
converters: {
"text json": function( textValue ) {
return jQuery.parseJSON(textValue.replace(/"\\\/Date\((-?\d*)\)\\\/"/g, "new Date($1)"));
}
}
});
Wednesday, April 13, 2011
Adding Better Ajax/JSON methods to HighCharts
I recently started using Highcharts as the charting options in Crystal Reports are rather limited. Here is a small patch I made to simplify the loading of chart data from JSON server calls via AJAX. This does not do anything incredibly unique, just simplifies the code to do so by adding an ajaxSource property to the chart and series configurations that is loaded on init and a reloadAjax method to automatically reload the data.
05/03/2011 - Rewrote the code as a extension instead of a patch and added support for setting multiple series via options.chart.ajaxSource.
05/03/2011 - Rewrote the code as a extension instead of a patch and added support for setting multiple series via options.chart.ajaxSource.
Subscribe to:
Posts (Atom)
Project Licenses
These works by Jeremy Pyne are licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License