Skip to content
Browse files

added jQuery BBQ and jQuery getObject plugins. Removed dependency on …

…Prototype for RSS feed url generation.
  • Loading branch information...
1 parent 26b0a9a commit 24160ea9f437d2c7c21aaa1c3dbbad324e32259a @chrisjacob committed Aug 3, 2010
View
153 public/javascripts/itunes_rss.js
@@ -1,13 +1,53 @@
(function( window, $, undefined ) {
var document = window.document,
+ json,
+ finalURL,
+ channelParams,
+ urlParams = window.location.search,
+ urlParamsObj = $.deparam.querystring(urlParams),
+ urlPath = window.location.pathname,
isWebAppItunesRss = {
options: {},
is_ready: false
};
isWebAppItunesRss.init = function init( options ){
this.options = $.extend({}, isWebAppItunesRss.defaults, options);
+
+ // set the default countryCode from the ?cc= param
+ this.countryCode = urlParamsObj.cc;
+ if (this.countryCode !== undefined) {
+ this.countryCode = this.countryCode.toUpperCase();
+ } else {
+ this.countryCode = "US";
+ }
+ $('#feedCountry').val(this.countryCode);
+
+ getData(this.countryCode);
+
+ $('#feedCountry').bind( 'change', function(){
+ var paramsStr = 'cc=' + $('#feedCountry').val();
+ window.location = $.param.querystring( window.location.href, paramsStr );
+ });
+
+ $('#feedMediaType').bind( 'focus change', function(){
+ if( typeof json !== undefined )
+ {
+ checkExplicit(json.list[this.selectedIndex]);
+ popFields(this.selectedIndex, 'types', '#feedType');
+ popFields(this.selectedIndex, 'genres', '#feedGenre');
+ }
+ });
+
+ $('#generate_btn').bind( 'click', function(){
+ genURL($('#feedMediaType').attr('selectedIndex'), $('#feedType').attr('selectedIndex'));
+ });
+
+ $('#preview_btn').bind( 'click', function(){
+ window.open(finalURL);
+ });
+
this.is_ready = true;
debug(this, options);
};
@@ -29,6 +69,119 @@ var document = window.document,
if (window.console && window.console.log) {
window.console.log(obj);
window.console.log(options);
+ window.console.log(urlParams);
+ window.console.log(urlParamsObj);
+ window.console.log(urlPath);
+ window.console.log(obj.countryCode);
+ }
+ }
+
+ // get data for the country
+ function getData(cc) {
+ // clear out any current options
+ $('#feedMediaType > option').remove();
+ $('#feedType > option').remove();
+ $('#feedGenre > option').remove();
+
+ $('#feedMediaType').removeAttr('disabled');
+
+ createOption( '#feedMediaType', 'Loading...' );
+
+ $.getScript( '/javascripts/wsAvailableFeeds/' + isWebAppItunesRss.countryCode + '.js', function(){
+ if(typeof availableFeeds !== 'undefined')
+ {
+ json = availableFeeds;
+ // window.console.log(json);
+
+ // load in mediaType options and focus on this field
+ var mediaType = availableFeeds.list;
+ $('#feedMediaType > option').remove();
+ $.each(mediaType, function(i, e){
+ createOption('#feedMediaType', e.display, e.name, isDefault(i));
+ });
+ $('#feedMediaType').focus();
+
+ $('#feedSize').removeAttr('disabled');
+
+ // populate feedType and feedGenre fields
+ if($('#feedMediaType > option').length > 0)
+ {
+ popFields(0, 'types', '#feedType');
+ popFields(0, 'genres', '#feedGenre');
+ }
+ }
+ });
+ }
+
+ // Populate subsequent select menus
+ function popFields(id, field, elem) {
+ if (id !== null) {
+ var feedTypes = $.getObject( 'list.'+ id +'.'+ field +'.list' , json );
+ if(feedTypes) {
+ $(elem +' > option').remove();
+
+ $.each(feedTypes, function(i, e){
+ if(field === 'genres') {
+ createOption(elem, e.display, e.value, isDefault(i));
+ } else {
+ createOption(elem, e.display, e.name, isDefault(i));
+ }
+ });
+
+ $(elem).removeAttr('disabled');
+ }
+ }
+ }
+
+ // Create and append a select option
+ function createOption(field, text, value, selected) {
+ var new_option = $('<option value="'+ value +'">'+ text +'</option>');
+ if(selected) {
+ new_option.attr( 'selected', 'selected');
+ }
+ $(field).append(new_option);
+ }
+
+ // Generate RSS URL
+ function genURL(media, index) {
+ var prefix = $.getObject( 'list.'+ media +'.types.list.'+ index +'.urlPrefix' , json ),
+ suffix = $.getObject( 'list.'+ media +'.types.list.'+ index +'.urlSuffix' , json ),
+ isExplicit = ( $('#feedEC > option:selected').val() === 'true' ) && $('#feedEC').is(':visible');
+
+ channelParams = "limit=" + $('#feedSize').val() + "/";
+
+ if( $('#feedGenre').val() !== '' ){
+ channelParams += "genre=" + $('#feedGenre').val() + "/";
+ }
+
+ if( isExplicit ) {
+ channelParams += "explicit=true/";
+ }
+
+ finalURL = prefix + channelParams + suffix;
+ $('#urlField').val(finalURL);
+ $('#urlOutput').show();
+
+ genIframe();
+ }
+
+ //Generate RSS iFrame
+ function genIframe() {
+ if( typeof finalURL !== 'undefined' ) {
+ $('#urlFieldIframe').attr('src', finalURL);
+ $('#urlOutputIframe').show();
+ }
+ }
+
+ // Select first option
+ function isDefault(n) {return n < 1;}
+
+ // Show/Hide Explicit options
+ function checkExplicit(type) {
+ if (type.canBeExplicit) {
+ $('#field_explicit').show();
+ } else {
+ $('#field_explicit').hide();
}
}
View
1,137 public/javascripts/jquery.ba-bbq.js
@@ -0,0 +1,1137 @@
+/*!
+ * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010
+ * http://benalman.com/projects/jquery-bbq-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+
+// Script: jQuery BBQ: Back Button & Query Library
+//
+// *Version: 1.2.1, Last updated: 2/17/2010*
+//
+// Project Home - http://benalman.com/projects/jquery-bbq-plugin/
+// GitHub - http://github.com/cowboy/jquery-bbq/
+// Source - http://github.com/cowboy/jquery-bbq/raw/master/jquery.ba-bbq.js
+// (Minified) - http://github.com/cowboy/jquery-bbq/raw/master/jquery.ba-bbq.min.js (4.0kb)
+//
+// About: License
+//
+// Copyright (c) 2010 "Cowboy" Ben Alman,
+// Dual licensed under the MIT and GPL licenses.
+// http://benalman.com/about/license/
+//
+// About: Examples
+//
+// These working examples, complete with fully commented code, illustrate a few
+// ways in which this plugin can be used.
+//
+// Basic AJAX - http://benalman.com/code/projects/jquery-bbq/examples/fragment-basic/
+// Advanced AJAX - http://benalman.com/code/projects/jquery-bbq/examples/fragment-advanced/
+// jQuery UI Tabs - http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs/
+// Deparam - http://benalman.com/code/projects/jquery-bbq/examples/deparam/
+//
+// About: Support and Testing
+//
+// Information about what version or versions of jQuery this plugin has been
+// tested with, what browsers it has been tested in, and where the unit tests
+// reside (so you can test it yourself).
+//
+// jQuery Versions - 1.3.2, 1.4.1, 1.4.2
+// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.7, Safari 3-4,
+// Chrome 4-5, Opera 9.6-10.1.
+// Unit Tests - http://benalman.com/code/projects/jquery-bbq/unit/
+//
+// About: Release History
+//
+// 1.2.1 - (2/17/2010) Actually fixed the stale window.location Safari bug from
+// <jQuery hashchange event> in BBQ, which was the main reason for the
+// previous release!
+// 1.2 - (2/16/2010) Integrated <jQuery hashchange event> v1.2, which fixes a
+// Safari bug, the event can now be bound before DOM ready, and IE6/7
+// page should no longer scroll when the event is first bound. Also
+// added the <jQuery.param.fragment.noEscape> method, and reworked the
+// <hashchange event (BBQ)> internal "add" method to be compatible with
+// changes made to the jQuery 1.4.2 special events API.
+// 1.1.1 - (1/22/2010) Integrated <jQuery hashchange event> v1.1, which fixes an
+// obscure IE8 EmulateIE7 meta tag compatibility mode bug.
+// 1.1 - (1/9/2010) Broke out the jQuery BBQ event.special <hashchange event>
+// functionality into a separate plugin for users who want just the
+// basic event & back button support, without all the extra awesomeness
+// that BBQ provides. This plugin will be included as part of jQuery BBQ,
+// but also be available separately. See <jQuery hashchange event>
+// plugin for more information. Also added the <jQuery.bbq.removeState>
+// method and added additional <jQuery.deparam> examples.
+// 1.0.3 - (12/2/2009) Fixed an issue in IE 6 where location.search and
+// location.hash would report incorrectly if the hash contained the ?
+// character. Also <jQuery.param.querystring> and <jQuery.param.fragment>
+// will no longer parse params out of a URL that doesn't contain ? or #,
+// respectively.
+// 1.0.2 - (10/10/2009) Fixed an issue in IE 6/7 where the hidden IFRAME caused
+// a "This page contains both secure and nonsecure items." warning when
+// used on an https:// page.
+// 1.0.1 - (10/7/2009) Fixed an issue in IE 8. Since both "IE7" and "IE8
+// Compatibility View" modes erroneously report that the browser
+// supports the native window.onhashchange event, a slightly more
+// robust test needed to be added.
+// 1.0 - (10/2/2009) Initial release
+
+(function($,window){
+ '$:nomunge'; // Used by YUI compressor.
+
+ // Some convenient shortcuts.
+ var undefined,
+ aps = Array.prototype.slice,
+ decode = decodeURIComponent,
+
+ // Method / object references.
+ jq_param = $.param,
+ jq_param_fragment,
+ jq_deparam,
+ jq_deparam_fragment,
+ jq_bbq = $.bbq = $.bbq || {},
+ jq_bbq_pushState,
+ jq_bbq_getState,
+ jq_elemUrlAttr,
+ jq_event_special = $.event.special,
+
+ // Reused strings.
+ str_hashchange = 'hashchange',
+ str_querystring = 'querystring',
+ str_fragment = 'fragment',
+ str_elemUrlAttr = 'elemUrlAttr',
+ str_location = 'location',
+ str_href = 'href',
+ str_src = 'src',
+
+ // Reused RegExp.
+ re_trim_querystring = /^.*\?|#.*$/g,
+ re_trim_fragment = /^.*\#/,
+ re_no_escape,
+
+ // Used by jQuery.elemUrlAttr.
+ elemUrlAttr_cache = {};
+
+ // A few commonly used bits, broken out to help reduce minified file size.
+
+ function is_string( arg ) {
+ return typeof arg === 'string';
+ };
+
+ // Why write the same function twice? Let's curry! Mmmm, curry..
+
+ function curry( func ) {
+ var args = aps.call( arguments, 1 );
+
+ return function() {
+ return func.apply( this, args.concat( aps.call( arguments ) ) );
+ };
+ };
+
+ // Get location.hash (or what you'd expect location.hash to be) sans any
+ // leading #. Thanks for making this necessary, Firefox!
+ function get_fragment( url ) {
+ return url.replace( /^[^#]*#?(.*)$/, '$1' );
+ };
+
+ // Get location.search (or what you'd expect location.search to be) sans any
+ // leading #. Thanks for making this necessary, IE6!
+ function get_querystring( url ) {
+ return url.replace( /(?:^[^?#]*\?([^#]*).*$)?.*/, '$1' );
+ };
+
+ // Section: Param (to string)
+ //
+ // Method: jQuery.param.querystring
+ //
+ // Retrieve the query string from a URL or if no arguments are passed, the
+ // current window.location.
+ //
+ // Usage:
+ //
+ // > jQuery.param.querystring( [ url ] );
+ //
+ // Arguments:
+ //
+ // url - (String) A URL containing query string params to be parsed. If url
+ // is not passed, the current window.location is used.
+ //
+ // Returns:
+ //
+ // (String) The parsed query string, with any leading "?" removed.
+ //
+
+ // Method: jQuery.param.querystring (build url)
+ //
+ // Merge a URL, with or without pre-existing query string params, plus any
+ // object, params string or URL containing query string params into a new URL.
+ //
+ // Usage:
+ //
+ // > jQuery.param.querystring( url, params [, merge_mode ] );
+ //
+ // Arguments:
+ //
+ // url - (String) A valid URL for params to be merged into. This URL may
+ // contain a query string and/or fragment (hash).
+ // params - (String) A params string or URL containing query string params to
+ // be merged into url.
+ // params - (Object) A params object to be merged into url.
+ // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not
+ // specified, and is as-follows:
+ //
+ // * 0: params in the params argument will override any query string
+ // params in url.
+ // * 1: any query string params in url will override params in the params
+ // argument.
+ // * 2: params argument will completely replace any query string in url.
+ //
+ // Returns:
+ //
+ // (String) Either a params string with urlencoded data or a URL with a
+ // urlencoded query string in the format 'a=b&c=d&e=f'.
+
+ // Method: jQuery.param.fragment
+ //
+ // Retrieve the fragment (hash) from a URL or if no arguments are passed, the
+ // current window.location.
+ //
+ // Usage:
+ //
+ // > jQuery.param.fragment( [ url ] );
+ //
+ // Arguments:
+ //
+ // url - (String) A URL containing fragment (hash) params to be parsed. If
+ // url is not passed, the current window.location is used.
+ //
+ // Returns:
+ //
+ // (String) The parsed fragment (hash) string, with any leading "#" removed.
+
+ // Method: jQuery.param.fragment (build url)
+ //
+ // Merge a URL, with or without pre-existing fragment (hash) params, plus any
+ // object, params string or URL containing fragment (hash) params into a new
+ // URL.
+ //
+ // Usage:
+ //
+ // > jQuery.param.fragment( url, params [, merge_mode ] );
+ //
+ // Arguments:
+ //
+ // url - (String) A valid URL for params to be merged into. This URL may
+ // contain a query string and/or fragment (hash).
+ // params - (String) A params string or URL containing fragment (hash) params
+ // to be merged into url.
+ // params - (Object) A params object to be merged into url.
+ // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not
+ // specified, and is as-follows:
+ //
+ // * 0: params in the params argument will override any fragment (hash)
+ // params in url.
+ // * 1: any fragment (hash) params in url will override params in the
+ // params argument.
+ // * 2: params argument will completely replace any query string in url.
+ //
+ // Returns:
+ //
+ // (String) Either a params string with urlencoded data or a URL with a
+ // urlencoded fragment (hash) in the format 'a=b&c=d&e=f'.
+
+ function jq_param_sub( is_fragment, get_func, url, params, merge_mode ) {
+ var result,
+ qs,
+ matches,
+ url_params,
+ hash;
+
+ if ( params !== undefined ) {
+ // Build URL by merging params into url string.
+
+ // matches[1] = url part that precedes params, not including trailing ?/#
+ // matches[2] = params, not including leading ?/#
+ // matches[3] = if in 'querystring' mode, hash including leading #, otherwise ''
+ matches = url.match( is_fragment ? /^([^#]*)\#?(.*)$/ : /^([^#?]*)\??([^#]*)(#?.*)/ );
+
+ // Get the hash if in 'querystring' mode, and it exists.
+ hash = matches[3] || '';
+
+ if ( merge_mode === 2 && is_string( params ) ) {
+ // If merge_mode is 2 and params is a string, merge the fragment / query
+ // string into the URL wholesale, without converting it into an object.
+ qs = params.replace( is_fragment ? re_trim_fragment : re_trim_querystring, '' );
+
+ } else {
+ // Convert relevant params in url to object.
+ url_params = jq_deparam( matches[2] );
+
+ params = is_string( params )
+
+ // Convert passed params string into object.
+ ? jq_deparam[ is_fragment ? str_fragment : str_querystring ]( params )
+
+ // Passed params object.
+ : params;
+
+ qs = merge_mode === 2 ? params // passed params replace url params
+ : merge_mode === 1 ? $.extend( {}, params, url_params ) // url params override passed params
+ : $.extend( {}, url_params, params ); // passed params override url params
+
+ // Convert params object to a string.
+ qs = jq_param( qs );
+
+ // Unescape characters specified via $.param.noEscape. Since only hash-
+ // history users have requested this feature, it's only enabled for
+ // fragment-related params strings.
+ if ( is_fragment ) {
+ qs = qs.replace( re_no_escape, decode );
+ }
+ }
+
+ // Build URL from the base url, querystring and hash. In 'querystring'
+ // mode, ? is only added if a query string exists. In 'fragment' mode, #
+ // is always added.
+ result = matches[1] + ( is_fragment ? '#' : qs || !matches[1] ? '?' : '' ) + qs + hash;
+
+ } else {
+ // If URL was passed in, parse params from URL string, otherwise parse
+ // params from window.location.
+ result = get_func( url !== undefined ? url : window[ str_location ][ str_href ] );
+ }
+
+ return result;
+ };
+
+ jq_param[ str_querystring ] = curry( jq_param_sub, 0, get_querystring );
+ jq_param[ str_fragment ] = jq_param_fragment = curry( jq_param_sub, 1, get_fragment );
+
+ // Method: jQuery.param.fragment.noEscape
+ //
+ // Specify characters that will be left unescaped when fragments are created
+ // or merged using <jQuery.param.fragment>, or when the fragment is modified
+ // using <jQuery.bbq.pushState>. This option only applies to serialized data
+ // object fragments, and not set-as-string fragments. Does not affect the
+ // query string. Defaults to ",/" (comma, forward slash).
+ //
+ // Note that this is considered a purely aesthetic option, and will help to
+ // create URLs that "look pretty" in the address bar or bookmarks, without
+ // affecting functionality in any way. That being said, be careful to not
+ // unescape characters that are used as delimiters or serve a special
+ // purpose, such as the "#?&=+" (octothorpe, question mark, ampersand,
+ // equals, plus) characters.
+ //
+ // Usage:
+ //
+ // > jQuery.param.fragment.noEscape( [ chars ] );
+ //
+ // Arguments:
+ //
+ // chars - (String) The characters to not escape in the fragment. If
+ // unspecified, defaults to empty string (escape all characters).
+ //
+ // Returns:
+ //
+ // Nothing.
+
+ jq_param_fragment.noEscape = function( chars ) {
+ chars = chars || '';
+ var arr = $.map( chars.split(''), encodeURIComponent );
+ re_no_escape = new RegExp( arr.join('|'), 'g' );
+ };
+
+ // A sensible default. These are the characters people seem to complain about
+ // "uglifying up the URL" the most.
+ jq_param_fragment.noEscape( ',/' );
+
+ // Section: Deparam (from string)
+ //
+ // Method: jQuery.deparam
+ //
+ // Deserialize a params string into an object, optionally coercing numbers,
+ // booleans, null and undefined values; this method is the counterpart to the
+ // internal jQuery.param method.
+ //
+ // Usage:
+ //
+ // > jQuery.deparam( params [, coerce ] );
+ //
+ // Arguments:
+ //
+ // params - (String) A params string to be parsed.
+ // coerce - (Boolean) If true, coerces any numbers or true, false, null, and
+ // undefined to their actual value. Defaults to false if omitted.
+ //
+ // Returns:
+ //
+ // (Object) An object representing the deserialized params string.
+
+ $.deparam = jq_deparam = function( params, coerce ) {
+ var obj = {},
+ coerce_types = { 'true': !0, 'false': !1, 'null': null };
+
+ // Iterate over all name=value pairs.
+ $.each( params.replace( /\+/g, ' ' ).split( '&' ), function(j,v){
+ var param = v.split( '=' ),
+ key = decode( param[0] ),
+ val,
+ cur = obj,
+ i = 0,
+
+ // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it
+ // into its component parts.
+ keys = key.split( '][' ),
+ keys_last = keys.length - 1;
+
+ // If the first keys part contains [ and the last ends with ], then []
+ // are correctly balanced.
+ if ( /\[/.test( keys[0] ) && /\]$/.test( keys[ keys_last ] ) ) {
+ // Remove the trailing ] from the last keys part.
+ keys[ keys_last ] = keys[ keys_last ].replace( /\]$/, '' );
+
+ // Split first keys part into two parts on the [ and add them back onto
+ // the beginning of the keys array.
+ keys = keys.shift().split('[').concat( keys );
+
+ keys_last = keys.length - 1;
+ } else {
+ // Basic 'foo' style key.
+ keys_last = 0;
+ }
+
+ // Are we dealing with a name=value pair, or just a name?
+ if ( param.length === 2 ) {
+ val = decode( param[1] );
+
+ // Coerce values.
+ if ( coerce ) {
+ val = val && !isNaN(val) ? +val // number
+ : val === 'undefined' ? undefined // undefined
+ : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null
+ : val; // string
+ }
+
+ if ( keys_last ) {
+ // Complex key, build deep object structure based on a few rules:
+ // * The 'cur' pointer starts at the object top-level.
+ // * [] = array push (n is set to array length), [n] = array if n is
+ // numeric, otherwise object.
+ // * If at the last keys part, set the value.
+ // * For each keys part, if the current level is undefined create an
+ // object or array based on the type of the next keys part.
+ // * Move the 'cur' pointer to the next level.
+ // * Rinse & repeat.
+ for ( ; i <= keys_last; i++ ) {
+ key = keys[i] === '' ? cur.length : keys[i];
+ cur = cur[key] = i < keys_last
+ ? cur[key] || ( keys[i+1] && isNaN( keys[i+1] ) ? {} : [] )
+ : val;
+ }
+
+ } else {
+ // Simple key, even simpler rules, since only scalars and shallow
+ // arrays are allowed.
+
+ if ( $.isArray( obj[key] ) ) {
+ // val is already an array, so push on the next value.
+ obj[key].push( val );
+
+ } else if ( obj[key] !== undefined ) {
+ // val isn't an array, but since a second value has been specified,
+ // convert val into an array.
+ obj[key] = [ obj[key], val ];
+
+ } else {
+ // val is a scalar.
+ obj[key] = val;
+ }
+ }
+
+ } else if ( key ) {
+ // No value was defined, so set something meaningful.
+ obj[key] = coerce
+ ? undefined
+ : '';
+ }
+ });
+
+ return obj;
+ };
+
+ // Method: jQuery.deparam.querystring
+ //
+ // Parse the query string from a URL or the current window.location,
+ // deserializing it into an object, optionally coercing numbers, booleans,
+ // null and undefined values.
+ //
+ // Usage:
+ //
+ // > jQuery.deparam.querystring( [ url ] [, coerce ] );
+ //
+ // Arguments:
+ //
+ // url - (String) An optional params string or URL containing query string
+ // params to be parsed. If url is omitted, the current window.location
+ // is used.
+ // coerce - (Boolean) If true, coerces any numbers or true, false, null, and
+ // undefined to their actual value. Defaults to false if omitted.
+ //
+ // Returns:
+ //
+ // (Object) An object representing the deserialized params string.
+
+ // Method: jQuery.deparam.fragment
+ //
+ // Parse the fragment (hash) from a URL or the current window.location,
+ // deserializing it into an object, optionally coercing numbers, booleans,
+ // null and undefined values.
+ //
+ // Usage:
+ //
+ // > jQuery.deparam.fragment( [ url ] [, coerce ] );
+ //
+ // Arguments:
+ //
+ // url - (String) An optional params string or URL containing fragment (hash)
+ // params to be parsed. If url is omitted, the current window.location
+ // is used.
+ // coerce - (Boolean) If true, coerces any numbers or true, false, null, and
+ // undefined to their actual value. Defaults to false if omitted.
+ //
+ // Returns:
+ //
+ // (Object) An object representing the deserialized params string.
+
+ function jq_deparam_sub( is_fragment, url_or_params, coerce ) {
+ if ( url_or_params === undefined || typeof url_or_params === 'boolean' ) {
+ // url_or_params not specified.
+ coerce = url_or_params;
+ url_or_params = jq_param[ is_fragment ? str_fragment : str_querystring ]();
+ } else {
+ url_or_params = is_string( url_or_params )
+ ? url_or_params.replace( is_fragment ? re_trim_fragment : re_trim_querystring, '' )
+ : url_or_params;
+ }
+
+ return jq_deparam( url_or_params, coerce );
+ };
+
+ jq_deparam[ str_querystring ] = curry( jq_deparam_sub, 0 );
+ jq_deparam[ str_fragment ] = jq_deparam_fragment = curry( jq_deparam_sub, 1 );
+
+ // Section: Element manipulation
+ //
+ // Method: jQuery.elemUrlAttr
+ //
+ // Get the internal "Default URL attribute per tag" list, or augment the list
+ // with additional tag-attribute pairs, in case the defaults are insufficient.
+ //
+ // In the <jQuery.fn.querystring> and <jQuery.fn.fragment> methods, this list
+ // is used to determine which attribute contains the URL to be modified, if
+ // an "attr" param is not specified.
+ //
+ // Default Tag-Attribute List:
+ //
+ // a - href
+ // base - href
+ // iframe - src
+ // img - src
+ // input - src
+ // form - action
+ // link - href
+ // script - src
+ //
+ // Usage:
+ //
+ // > jQuery.elemUrlAttr( [ tag_attr ] );
+ //
+ // Arguments:
+ //
+ // tag_attr - (Object) An object containing a list of tag names and their
+ // associated default attribute names in the format { tag: 'attr', ... } to
+ // be merged into the internal tag-attribute list.
+ //
+ // Returns:
+ //
+ // (Object) An object containing all stored tag-attribute values.
+
+ // Only define function and set defaults if function doesn't already exist, as
+ // the urlInternal plugin will provide this method as well.
+ $[ str_elemUrlAttr ] || ($[ str_elemUrlAttr ] = function( obj ) {
+ return $.extend( elemUrlAttr_cache, obj );
+ })({
+ a: str_href,
+ base: str_href,
+ iframe: str_src,
+ img: str_src,
+ input: str_src,
+ form: 'action',
+ link: str_href,
+ script: str_src
+ });
+
+ jq_elemUrlAttr = $[ str_elemUrlAttr ];
+
+ // Method: jQuery.fn.querystring
+ //
+ // Update URL attribute in one or more elements, merging the current URL (with
+ // or without pre-existing query string params) plus any params object or
+ // string into a new URL, which is then set into that attribute. Like
+ // <jQuery.param.querystring (build url)>, but for all elements in a jQuery
+ // collection.
+ //
+ // Usage:
+ //
+ // > jQuery('selector').querystring( [ attr, ] params [, merge_mode ] );
+ //
+ // Arguments:
+ //
+ // attr - (String) Optional name of an attribute that will contain a URL to
+ // merge params or url into. See <jQuery.elemUrlAttr> for a list of default
+ // attributes.
+ // params - (Object) A params object to be merged into the URL attribute.
+ // params - (String) A URL containing query string params, or params string
+ // to be merged into the URL attribute.
+ // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not
+ // specified, and is as-follows:
+ //
+ // * 0: params in the params argument will override any params in attr URL.
+ // * 1: any params in attr URL will override params in the params argument.
+ // * 2: params argument will completely replace any query string in attr
+ // URL.
+ //
+ // Returns:
+ //
+ // (jQuery) The initial jQuery collection of elements, but with modified URL
+ // attribute values.
+
+ // Method: jQuery.fn.fragment
+ //
+ // Update URL attribute in one or more elements, merging the current URL (with
+ // or without pre-existing fragment/hash params) plus any params object or
+ // string into a new URL, which is then set into that attribute. Like
+ // <jQuery.param.fragment (build url)>, but for all elements in a jQuery
+ // collection.
+ //
+ // Usage:
+ //
+ // > jQuery('selector').fragment( [ attr, ] params [, merge_mode ] );
+ //
+ // Arguments:
+ //
+ // attr - (String) Optional name of an attribute that will contain a URL to
+ // merge params into. See <jQuery.elemUrlAttr> for a list of default
+ // attributes.
+ // params - (Object) A params object to be merged into the URL attribute.
+ // params - (String) A URL containing fragment (hash) params, or params
+ // string to be merged into the URL attribute.
+ // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not
+ // specified, and is as-follows:
+ //
+ // * 0: params in the params argument will override any params in attr URL.
+ // * 1: any params in attr URL will override params in the params argument.
+ // * 2: params argument will completely replace any fragment (hash) in attr
+ // URL.
+ //
+ // Returns:
+ //
+ // (jQuery) The initial jQuery collection of elements, but with modified URL
+ // attribute values.
+
+ function jq_fn_sub( mode, force_attr, params, merge_mode ) {
+ if ( !is_string( params ) && typeof params !== 'object' ) {
+ // force_attr not specified.
+ merge_mode = params;
+ params = force_attr;
+ force_attr = undefined;
+ }
+
+ return this.each(function(){
+ var that = $(this),
+
+ // Get attribute specified, or default specified via $.elemUrlAttr.
+ attr = force_attr || jq_elemUrlAttr()[ ( this.nodeName || '' ).toLowerCase() ] || '',
+
+ // Get URL value.
+ url = attr && that.attr( attr ) || '';
+
+ // Update attribute with new URL.
+ that.attr( attr, jq_param[ mode ]( url, params, merge_mode ) );
+ });
+
+ };
+
+ $.fn[ str_querystring ] = curry( jq_fn_sub, str_querystring );
+ $.fn[ str_fragment ] = curry( jq_fn_sub, str_fragment );
+
+ // Section: History, hashchange event
+ //
+ // Method: jQuery.bbq.pushState
+ //
+ // Adds a 'state' into the browser history at the current position, setting
+ // location.hash and triggering any bound <hashchange event> callbacks
+ // (provided the new state is different than the previous state).
+ //
+ // If no arguments are passed, an empty state is created, which is just a
+ // shortcut for jQuery.bbq.pushState( {}, 2 ).
+ //
+ // Usage:
+ //
+ // > jQuery.bbq.pushState( [ params [, merge_mode ] ] );
+ //
+ // Arguments:
+ //
+ // params - (String) A serialized params string or a hash string beginning
+ // with # to merge into location.hash.
+ // params - (Object) A params object to merge into location.hash.
+ // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not
+ // specified (unless a hash string beginning with # is specified, in which
+ // case merge behavior defaults to 2), and is as-follows:
+ //
+ // * 0: params in the params argument will override any params in the
+ // current state.
+ // * 1: any params in the current state will override params in the params
+ // argument.
+ // * 2: params argument will completely replace current state.
+ //
+ // Returns:
+ //
+ // Nothing.
+ //
+ // Additional Notes:
+ //
+ // * Setting an empty state may cause the browser to scroll.
+ // * Unlike the fragment and querystring methods, if a hash string beginning
+ // with # is specified as the params agrument, merge_mode defaults to 2.
+
+ jq_bbq.pushState = jq_bbq_pushState = function( params, merge_mode ) {
+ if ( is_string( params ) && /^#/.test( params ) && merge_mode === undefined ) {
+ // Params string begins with # and merge_mode not specified, so completely
+ // overwrite window.location.hash.
+ merge_mode = 2;
+ }
+
+ var has_args = params !== undefined,
+ // Merge params into window.location using $.param.fragment.
+ url = jq_param_fragment( window[ str_location ][ str_href ],
+ has_args ? params : {}, has_args ? merge_mode : 2 );
+
+ // Set new window.location.href. If hash is empty, use just # to prevent
+ // browser from reloading the page. Note that Safari 3 & Chrome barf on
+ // location.hash = '#'.
+ window[ str_location ][ str_href ] = url + ( /#/.test( url ) ? '' : '#' );
+ };
+
+ // Method: jQuery.bbq.getState
+ //
+ // Retrieves the current 'state' from the browser history, parsing
+ // location.hash for a specific key or returning an object containing the
+ // entire state, optionally coercing numbers, booleans, null and undefined
+ // values.
+ //
+ // Usage:
+ //
+ // > jQuery.bbq.getState( [ key ] [, coerce ] );
+ //
+ // Arguments:
+ //
+ // key - (String) An optional state key for which to return a value.
+ // coerce - (Boolean) If true, coerces any numbers or true, false, null, and
+ // undefined to their actual value. Defaults to false.
+ //
+ // Returns:
+ //
+ // (Anything) If key is passed, returns the value corresponding with that key
+ // in the location.hash 'state', or undefined. If not, an object
+ // representing the entire 'state' is returned.
+
+ jq_bbq.getState = jq_bbq_getState = function( key, coerce ) {
+ return key === undefined || typeof key === 'boolean'
+ ? jq_deparam_fragment( key ) // 'key' really means 'coerce' here
+ : jq_deparam_fragment( coerce )[ key ];
+ };
+
+ // Method: jQuery.bbq.removeState
+ //
+ // Remove one or more keys from the current browser history 'state', creating
+ // a new state, setting location.hash and triggering any bound
+ // <hashchange event> callbacks (provided the new state is different than
+ // the previous state).
+ //
+ // If no arguments are passed, an empty state is created, which is just a
+ // shortcut for jQuery.bbq.pushState( {}, 2 ).
+ //
+ // Usage:
+ //
+ // > jQuery.bbq.removeState( [ key [, key ... ] ] );
+ //
+ // Arguments:
+ //
+ // key - (String) One or more key values to remove from the current state,
+ // passed as individual arguments.
+ // key - (Array) A single array argument that contains a list of key values
+ // to remove from the current state.
+ //
+ // Returns:
+ //
+ // Nothing.
+ //
+ // Additional Notes:
+ //
+ // * Setting an empty state may cause the browser to scroll.
+
+ jq_bbq.removeState = function( arr ) {
+ var state = {};
+
+ // If one or more arguments is passed..
+ if ( arr !== undefined ) {
+
+ // Get the current state.
+ state = jq_bbq_getState();
+
+ // For each passed key, delete the corresponding property from the current
+ // state.
+ $.each( $.isArray( arr ) ? arr : arguments, function(i,v){
+ delete state[ v ];
+ });
+ }
+
+ // Set the state, completely overriding any existing state.
+ jq_bbq_pushState( state, 2 );
+ };
+
+ // Event: hashchange event (BBQ)
+ //
+ // Usage in jQuery 1.4 and newer:
+ //
+ // In jQuery 1.4 and newer, the event object passed into any hashchange event
+ // callback is augmented with a copy of the location.hash fragment at the time
+ // the event was triggered as its event.fragment property. In addition, the
+ // event.getState method operates on this property (instead of location.hash)
+ // which allows this fragment-as-a-state to be referenced later, even after
+ // window.location may have changed.
+ //
+ // Note that event.fragment and event.getState are not defined according to
+ // W3C (or any other) specification, but will still be available whether or
+ // not the hashchange event exists natively in the browser, because of the
+ // utility they provide.
+ //
+ // The event.fragment property contains the output of <jQuery.param.fragment>
+ // and the event.getState method is equivalent to the <jQuery.bbq.getState>
+ // method.
+ //
+ // > $(window).bind( 'hashchange', function( event ) {
+ // > var hash_str = event.fragment,
+ // > param_obj = event.getState(),
+ // > param_val = event.getState( 'param_name' ),
+ // > param_val_coerced = event.getState( 'param_name', true );
+ // > ...
+ // > });
+ //
+ // Usage in jQuery 1.3.2:
+ //
+ // In jQuery 1.3.2, the event object cannot to be augmented as in jQuery 1.4+,
+ // so the fragment state isn't bound to the event object and must instead be
+ // parsed using the <jQuery.param.fragment> and <jQuery.bbq.getState> methods.
+ //
+ // > $(window).bind( 'hashchange', function( event ) {
+ // > var hash_str = $.param.fragment(),
+ // > param_obj = $.bbq.getState(),
+ // > param_val = $.bbq.getState( 'param_name' ),
+ // > param_val_coerced = $.bbq.getState( 'param_name', true );
+ // > ...
+ // > });
+ //
+ // Additional Notes:
+ //
+ // * Due to changes in the special events API, jQuery BBQ v1.2 or newer is
+ // required to enable the augmented event object in jQuery 1.4.2 and newer.
+ // * See <jQuery hashchange event> for more detailed information.
+
+ jq_event_special[ str_hashchange ] = $.extend( jq_event_special[ str_hashchange ], {
+
+ // Augmenting the event object with the .fragment property and .getState
+ // method requires jQuery 1.4 or newer. Note: with 1.3.2, everything will
+ // work, but the event won't be augmented)
+ add: function( handleObj ) {
+ var old_handler;
+
+ function new_handler(e) {
+ // e.fragment is set to the value of location.hash (with any leading #
+ // removed) at the time the event is triggered.
+ var hash = e[ str_fragment ] = jq_param_fragment();
+
+ // e.getState() works just like $.bbq.getState(), but uses the
+ // e.fragment property stored on the event object.
+ e.getState = function( key, coerce ) {
+ return key === undefined || typeof key === 'boolean'
+ ? jq_deparam( hash, key ) // 'key' really means 'coerce' here
+ : jq_deparam( hash, coerce )[ key ];
+ };
+
+ old_handler.apply( this, arguments );
+ };
+
+ // This may seem a little complicated, but it normalizes the special event
+ // .add method between jQuery 1.4/1.4.1 and 1.4.2+
+ if ( $.isFunction( handleObj ) ) {
+ // 1.4, 1.4.1
+ old_handler = handleObj;
+ return new_handler;
+ } else {
+ // 1.4.2+
+ old_handler = handleObj.handler;
+ handleObj.handler = new_handler;
+ }
+ }
+
+ });
+
+})(jQuery,this);
+
+/*!
+ * jQuery hashchange event - v1.2 - 2/11/2010
+ * http://benalman.com/projects/jquery-hashchange-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+
+// Script: jQuery hashchange event
+//
+// *Version: 1.2, Last updated: 2/11/2010*
+//
+// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/
+// GitHub - http://github.com/cowboy/jquery-hashchange/
+// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js
+// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (1.1kb)
+//
+// About: License
+//
+// Copyright (c) 2010 "Cowboy" Ben Alman,
+// Dual licensed under the MIT and GPL licenses.
+// http://benalman.com/about/license/
+//
+// About: Examples
+//
+// This working example, complete with fully commented code, illustrate one way
+// in which this plugin can be used.
+//
+// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/
+//
+// About: Support and Testing
+//
+// Information about what version or versions of jQuery this plugin has been
+// tested with, what browsers it has been tested in, and where the unit tests
+// reside (so you can test it yourself).
+//
+// jQuery Versions - 1.3.2, 1.4.1, 1.4.2
+// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.7, Safari 3-4, Chrome, Opera 9.6-10.1.
+// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/
+//
+// About: Known issues
+//
+// While this jQuery hashchange event implementation is quite stable and robust,
+// there are a few unfortunate browser bugs surrounding expected hashchange
+// event-based behaviors, independent of any JavaScript window.onhashchange
+// abstraction. See the following examples for more information:
+//
+// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/
+// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/
+// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/
+// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/
+//
+// About: Release History
+//
+// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin
+// from a page on another domain would cause an error in Safari 4. Also,
+// IE6/7 Iframe is now inserted after the body (this actually works),
+// which prevents the page from scrolling when the event is first bound.
+// Event can also now be bound before DOM ready, but it won't be usable
+// before then in IE6/7.
+// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug
+// where browser version is incorrectly reported as 8.0, despite
+// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.
+// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special
+// window.onhashchange functionality into a separate plugin for users
+// who want just the basic event & back button support, without all the
+// extra awesomeness that BBQ provides. This plugin will be included as
+// part of jQuery BBQ, but also be available separately.
+
+(function($,window,undefined){
+ '$:nomunge'; // Used by YUI compressor.
+
+ // Method / object references.
+ var fake_onhashchange,
+ jq_event_special = $.event.special,
+
+ // Reused strings.
+ str_location = 'location',
+ str_hashchange = 'hashchange',
+ str_href = 'href',
+
+ // IE6/7 specifically need some special love when it comes to back-button
+ // support, so let's do a little browser sniffing..
+ browser = $.browser,
+ mode = document.documentMode,
+ is_old_ie = browser.msie && ( mode === undefined || mode < 8 ),
+
+ // Does the browser support window.onhashchange? Test for IE version, since
+ // IE8 incorrectly reports this when in "IE7" or "IE8 Compatibility View"!
+ supports_onhashchange = 'on' + str_hashchange in window && !is_old_ie;
+
+ // Get location.hash (or what you'd expect location.hash to be) sans any
+ // leading #. Thanks for making this necessary, Firefox!
+ function get_fragment( url ) {
+ url = url || window[ str_location ][ str_href ];
+ return url.replace( /^[^#]*#?(.*)$/, '$1' );
+ };
+
+ // Property: jQuery.hashchangeDelay
+ //
+ // The numeric interval (in milliseconds) at which the <hashchange event>
+ // polling loop executes. Defaults to 100.
+
+ $[ str_hashchange + 'Delay' ] = 100;
+
+ // Event: hashchange event
+ //
+ // Fired when location.hash changes. In browsers that support it, the native
+ // window.onhashchange event is used (IE8, FF3.6), otherwise a polling loop is
+ // initialized, running every <jQuery.hashchangeDelay> milliseconds to see if
+ // the hash has changed. In IE 6 and 7, a hidden Iframe is created to allow
+ // the back button and hash-based history to work.
+ //
+ // Usage:
+ //
+ // > $(window).bind( 'hashchange', function(e) {
+ // > var hash = location.hash;
+ // > ...
+ // > });
+ //
+ // Additional Notes:
+ //
+ // * The polling loop and Iframe are not created until at least one callback
+ // is actually bound to 'hashchange'.
+ // * If you need the bound callback(s) to execute immediately, in cases where
+ // the page 'state' exists on page load (via bookmark or page refresh, for
+ // example) use $(window).trigger( 'hashchange' );
+ // * The event can be bound before DOM ready, but since it won't be usable
+ // before then in IE6/7 (due to the necessary Iframe), recommended usage is
+ // to bind it inside a $(document).ready() callback.
+
+ jq_event_special[ str_hashchange ] = $.extend( jq_event_special[ str_hashchange ], {
+
+ // Called only when the first 'hashchange' event is bound to window.
+ setup: function() {
+ // If window.onhashchange is supported natively, there's nothing to do..
+ if ( supports_onhashchange ) { return false; }
+
+ // Otherwise, we need to create our own. And we don't want to call this
+ // until the user binds to the event, just in case they never do, since it
+ // will create a polling loop and possibly even a hidden Iframe.
+ $( fake_onhashchange.start );
+ },
+
+ // Called only when the last 'hashchange' event is unbound from window.
+ teardown: function() {
+ // If window.onhashchange is supported natively, there's nothing to do..
+ if ( supports_onhashchange ) { return false; }
+
+ // Otherwise, we need to stop ours (if possible).
+ $( fake_onhashchange.stop );
+ }
+
+ });
+
+ // fake_onhashchange does all the work of triggering the window.onhashchange
+ // event for browsers that don't natively support it, including creating a
+ // polling loop to watch for hash changes and in IE 6/7 creating a hidden
+ // Iframe to enable back and forward.
+ fake_onhashchange = (function(){
+ var self = {},
+ timeout_id,
+ iframe,
+ set_history,
+ get_history;
+
+ // Initialize. In IE 6/7, creates a hidden Iframe for history handling.
+ function init(){
+ // Most browsers don't need special methods here..
+ set_history = get_history = function(val){ return val; };
+
+ // But IE6/7 do!
+ if ( is_old_ie ) {
+
+ // Create hidden Iframe after the end of the body to prevent initial
+ // page load from scrolling unnecessarily.
+ iframe = $('<iframe src="javascript:0"/>').hide().insertAfter( 'body' )[0].contentWindow;
+
+ // Get history by looking at the hidden Iframe's location.hash.
+ get_history = function() {
+ return get_fragment( iframe.document[ str_location ][ str_href ] );
+ };
+
+ // Set a new history item by opening and then closing the Iframe
+ // document, *then* setting its location.hash.
+ set_history = function( hash, history_hash ) {
+ if ( hash !== history_hash ) {
+ var doc = iframe.document;
+ doc.open().close();
+ doc[ str_location ].hash = '#' + hash;
+ }
+ };
+
+ // Set initial history.
+ set_history( get_fragment() );
+ }
+ };
+
+ // Start the polling loop.
+ self.start = function() {
+ // Polling loop is already running!
+ if ( timeout_id ) { return; }
+
+ // Remember the initial hash so it doesn't get triggered immediately.
+ var last_hash = get_fragment();
+
+ // Initialize if not yet initialized.
+ set_history || init();
+
+ // This polling loop checks every $.hashchangeDelay milliseconds to see if
+ // location.hash has changed, and triggers the 'hashchange' event on
+ // window when necessary.
+ (function loopy(){
+ var hash = get_fragment(),
+ history_hash = get_history( last_hash );
+
+ if ( hash !== last_hash ) {
+ set_history( last_hash = hash, history_hash );
+
+ $(window).trigger( str_hashchange );
+
+ } else if ( history_hash !== last_hash ) {
+ window[ str_location ][ str_href ] = window[ str_location ][ str_href ].replace( /#.*/, '' ) + '#' + history_hash;
+ }
+
+ timeout_id = setTimeout( loopy, $[ str_hashchange + 'Delay' ] );
+ })();
+ };
+
+ // Stop the polling loop, but only if an IE6/7 Iframe wasn't created. In
+ // that case, even if there are no longer any bound event handlers, the
+ // polling loop is still necessary for back/next to work at all!
+ self.stop = function() {
+ if ( !iframe ) {
+ timeout_id && clearTimeout( timeout_id );
+ timeout_id = 0;
+ }
+ };
+
+ return self;
+ })();
+
+})(jQuery,this);
View
18 public/javascripts/jquery.ba-bbq.min.js
@@ -0,0 +1,18 @@
+/*
+ * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010
+ * http://benalman.com/projects/jquery-bbq-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+(function($,p){var i,m=Array.prototype.slice,r=decodeURIComponent,a=$.param,c,l,v,b=$.bbq=$.bbq||{},q,u,j,e=$.event.special,d="hashchange",A="querystring",D="fragment",y="elemUrlAttr",g="location",k="href",t="src",x=/^.*\?|#.*$/g,w=/^.*\#/,h,C={};function E(F){return typeof F==="string"}function B(G){var F=m.call(arguments,1);return function(){return G.apply(this,F.concat(m.call(arguments)))}}function n(F){return F.replace(/^[^#]*#?(.*)$/,"$1")}function o(F){return F.replace(/(?:^[^?#]*\?([^#]*).*$)?.*/,"$1")}function f(H,M,F,I,G){var O,L,K,N,J;if(I!==i){K=F.match(H?/^([^#]*)\#?(.*)$/:/^([^#?]*)\??([^#]*)(#?.*)/);J=K[3]||"";if(G===2&&E(I)){L=I.replace(H?w:x,"")}else{N=l(K[2]);I=E(I)?l[H?D:A](I):I;L=G===2?I:G===1?$.extend({},I,N):$.extend({},N,I);L=a(L);if(H){L=L.replace(h,r)}}O=K[1]+(H?"#":L||!K[1]?"?":"")+L+J}else{O=M(F!==i?F:p[g][k])}return O}a[A]=B(f,0,o);a[D]=c=B(f,1,n);c.noEscape=function(G){G=G||"";var F=$.map(G.split(""),encodeURIComponent);h=new RegExp(F.join("|"),"g")};c.noEscape(",/");$.deparam=l=function(I,F){var H={},G={"true":!0,"false":!1,"null":null};$.each(I.replace(/\+/g," ").split("&"),function(L,Q){var K=Q.split("="),P=r(K[0]),J,O=H,M=0,R=P.split("]["),N=R.length-1;if(/\[/.test(R[0])&&/\]$/.test(R[N])){R[N]=R[N].replace(/\]$/,"");R=R.shift().split("[").concat(R);N=R.length-1}else{N=0}if(K.length===2){J=r(K[1]);if(F){J=J&&!isNaN(J)?+J:J==="undefined"?i:G[J]!==i?G[J]:J}if(N){for(;M<=N;M++){P=R[M]===""?O.length:R[M];O=O[P]=M<N?O[P]||(R[M+1]&&isNaN(R[M+1])?{}:[]):J}}else{if($.isArray(H[P])){H[P].push(J)}else{if(H[P]!==i){H[P]=[H[P],J]}else{H[P]=J}}}}else{if(P){H[P]=F?i:""}}});return H};function z(H,F,G){if(F===i||typeof F==="boolean"){G=F;F=a[H?D:A]()}else{F=E(F)?F.replace(H?w:x,""):F}return l(F,G)}l[A]=B(z,0);l[D]=v=B(z,1);$[y]||($[y]=function(F){return $.extend(C,F)})({a:k,base:k,iframe:t,img:t,input:t,form:"action",link:k,script:t});j=$[y];function s(I,G,H,F){if(!E(H)&&typeof H!=="object"){F=H;H=G;G=i}return this.each(function(){var L=$(this),J=G||j()[(this.nodeName||"").toLowerCase()]||"",K=J&&L.attr(J)||"";L.attr(J,a[I](K,H,F))})}$.fn[A]=B(s,A);$.fn[D]=B(s,D);b.pushState=q=function(I,F){if(E(I)&&/^#/.test(I)&&F===i){F=2}var H=I!==i,G=c(p[g][k],H?I:{},H?F:2);p[g][k]=G+(/#/.test(G)?"":"#")};b.getState=u=function(F,G){return F===i||typeof F==="boolean"?v(F):v(G)[F]};b.removeState=function(F){var G={};if(F!==i){G=u();$.each($.isArray(F)?F:arguments,function(I,H){delete G[H]})}q(G,2)};e[d]=$.extend(e[d],{add:function(F){var H;function G(J){var I=J[D]=c();J.getState=function(K,L){return K===i||typeof K==="boolean"?l(I,K):l(I,L)[K]};H.apply(this,arguments)}if($.isFunction(F)){H=F;return G}else{H=F.handler;F.handler=G}}})})(jQuery,this);
+/*
+ * jQuery hashchange event - v1.2 - 2/11/2010
+ * http://benalman.com/projects/jquery-hashchange-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+(function($,i,b){var j,k=$.event.special,c="location",d="hashchange",l="href",f=$.browser,g=document.documentMode,h=f.msie&&(g===b||g<8),e="on"+d in i&&!h;function a(m){m=m||i[c][l];return m.replace(/^[^#]*#?(.*)$/,"$1")}$[d+"Delay"]=100;k[d]=$.extend(k[d],{setup:function(){if(e){return false}$(j.start)},teardown:function(){if(e){return false}$(j.stop)}});j=(function(){var m={},r,n,o,q;function p(){o=q=function(s){return s};if(h){n=$('<iframe src="javascript:0"/>').hide().insertAfter("body")[0].contentWindow;q=function(){return a(n.document[c][l])};o=function(u,s){if(u!==s){var t=n.document;t.open().close();t[c].hash="#"+u}};o(a())}}m.start=function(){if(r){return}var t=a();o||p();(function s(){var v=a(),u=q(t);if(v!==t){o(t=v,u);$(i).trigger(d)}else{if(u!==t){i[c][l]=i[c][l].replace(/#.*/,"")+"#"+u}}r=setTimeout(s,$[d+"Delay"])})()};m.stop=function(){if(!n){r&&clearTimeout(r);r=0}};return m})()})(jQuery,this);
View
177 public/javascripts/jquery.ba-getobject.js
@@ -0,0 +1,177 @@
+/*!
+ * jQuery getObject - v1.1 - 12/24/2009
+ * http://benalman.com/projects/jquery-getobject-plugin/
+ *
+ * Copyright (c) 2009 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ *
+ * Inspired by Dojo, which is Copyright (c) 2005-2009, The Dojo Foundation.
+ */
+
+// Script: jQuery getObject: get.and.set.deep.objects.easily = true;
+//
+// *Version: 1.1, Last updated: 12/24/2009*
+//
+// Project Home - http://benalman.com/projects/jquery-getobject-plugin/
+// GitHub - http://github.com/cowboy/jquery-getobject/
+// Source - http://github.com/cowboy/jquery-getobject/raw/master/jquery.ba-getobject.js
+// (Minified) - http://github.com/cowboy/jquery-getobject/raw/master/jquery.ba-getobject.min.js (0.7kb)
+//
+// About: License
+//
+// Copyright (c) 2009 "Cowboy" Ben Alman,
+// Dual licensed under the MIT and GPL licenses.
+// http://benalman.com/about/license/
+//
+// Inspired by Dojo, which is Copyright (c) 2005-2009, The Dojo Foundation.
+//
+// About: Support and Testing
+//
+// Information about what version or versions of jQuery this plugin has been
+// tested with, what browsers it has been tested in, and where the unit tests
+// reside (so you can test it yourself).
+//
+// jQuery Versions - none, 1.3.2, 1.4a2
+// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome, Opera 9.6-10.
+// Unit Tests - http://benalman.com/code/projects/jquery-getobject/unit/
+//
+// About: Release History
+//
+// 1.1 - (12/24/2009) Removed dependency on jQuery. Now creates methods in a
+// `Cowboy` namespace if jQuery isn't present.
+// 1.0 - (12/19/2009) Initial release
+//
+// Topic: Note for non-jQuery users
+//
+// jQuery isn't actually required for this plugin, because nothing internal
+// uses any jQuery methods or properties. jQuery is just used as a namespace
+// under which these methods can exist.
+//
+// Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
+// when this plugin is loaded, the methods described below will be created in
+// the `Cowboy` namespace. Usage will be exactly the same, but instead of
+// $.method() or jQuery.method(), you'll need to use Cowboy.method().
+//
+// Topic: Note for Dojo users
+//
+// The setObject, getObject, and exists methods are similar to their Dojo
+// counterparts, with the exception that exists returns true or false based
+// on whether or not a property is defined, not whether it is truthy.
+
+(function(window,undefined){
+ '$:nomunge'; // Used by YUI compressor.
+
+ // Since jQuery really isn't required for this plugin, use `jQuery` as the
+ // namespace only if it already exists, otherwise use the `Cowboy` namespace,
+ // creating it if necessary.
+ var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
+
+ // Method reference.
+ jq_getObject;
+
+ // Method: jQuery.getObject
+ //
+ // Get a property of an object via dot-delimited name string, and optionally
+ // create the property and any ancestor properties that do not already exist.
+ //
+ // Usage:
+ //
+ // > jQuery.getObject( name [, create ] [, context ] );
+ //
+ // Arguments:
+ //
+ // name - (String) Dot-delimited string representing a property name, for
+ // example: 'document', 'location.href', 'window.open' or 'foo.bar.baz'.
+ // create - (Boolean) Create final and intermediate properties if they don't
+ // exist. Defaults to false.
+ // context - (Object) Optional context in which to evaluate name. Defaults to
+ // window if omitted.
+ //
+ // Returns:
+ //
+ // (Object) An object reference or value on success, otherwise undefined.
+
+ $.getObject = jq_getObject = function( parts, create, obj ) {
+
+ if ( typeof parts === 'string' ) {
+ parts = parts.split('.');
+ }
+
+ if ( typeof create !== 'boolean' ) {
+ obj = create;
+ create = undefined;
+ }
+
+ obj = obj || window;
+
+ var p;
+
+ while ( obj && parts.length ) {
+ p = parts.shift();
+ if ( obj[p] === undefined && create ) {
+ obj[p] = {};
+ }
+ obj = obj[p];
+ }
+
+ return obj;
+ };
+
+ // Method: jQuery.setObject
+ //
+ // Set a property of an object via dot-delimited name string, creating any
+ // ancestor properties that do not already exist.
+ //
+ // Usage:
+ //
+ // > jQuery.setObject( name, value, [ context ] );
+ //
+ // Arguments:
+ //
+ // name - (String) Dot-delimited string representing a property name, for
+ // example: 'document', 'location.href', 'window.open' or 'foo.bar.baz'.
+ // value - (Anything) Any valid JavaScript expression.
+ // context - (Object) Optional context in which to evaluate name. Defaults to
+ // window if omitted.
+ //
+ // Returns:
+ //
+ // (Anything) The value if set successfully, otherwise undefined.
+
+ $.setObject = function( name, value, context ) {
+ var parts = name.split('.'),
+ prop = parts.pop(),
+ obj = jq_getObject( parts, true, context );
+
+ // Only return the value if it is set successfully.
+ return obj && typeof obj === 'object' && prop
+ ? ( obj[prop] = value )
+ : undefined;
+ };
+
+ // Method: jQuery.exists
+ //
+ // Using dot-delimited name string, return whether a property of an object
+ // exists.
+ //
+ // Usage:
+ //
+ // > jQuery.exists( name [, context ] );
+ //
+ // Arguments:
+ //
+ // name - (String) Dot-delimited string representing a property name, for
+ // example: 'document', 'location.href', 'window.open' or 'foo.bar.baz'.
+ // context - (Object) Optional context in which to evaluate name. Defaults to
+ // window if omitted.
+ //
+ // Returns:
+ //
+ // (Boolean) Whether or not the property exists.
+
+ $.exists = function( name, context ) {
+ return jq_getObject( name, context ) !== undefined;
+ };
+
+})(this);
View
11 public/javascripts/jquery.ba-getobject.min.js
@@ -0,0 +1,11 @@
+/*
+ * jQuery getObject - v1.1 - 12/24/2009
+ * http://benalman.com/projects/jquery-getobject-plugin/
+ *
+ * Copyright (c) 2009 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ *
+ * Inspired by Dojo, which is Copyright (c) 2005-2009, The Dojo Foundation.
+ */
+(function(a,c){var $=a.jQuery||a.Cowboy||(a.Cowboy={}),b;$.getObject=b=function(g,d,f){if(typeof g==="string"){g=g.split(".")}if(typeof d!=="boolean"){f=d;d=c}f=f||a;var e;while(f&&g.length){e=g.shift();if(f[e]===c&&d){f[e]={}}f=f[e]}return f};$.setObject=function(d,f,e){var h=d.split("."),i=h.pop(),g=b(h,true,e);return g&&typeof g==="object"&&i?(g[i]=f):c};$.exists=function(d,e){return b(d,e)!==c}})(this);
View
65 public/javascripts/wsAvailableFeeds/AU.js
@@ -0,0 +1,65 @@
+availableFeeds={"display":"Media Type", "name":"mediaType", "list":[
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}, {"value":"20", "display":"Alternative"}, {"value":"2", "display":"Blues"},
+{"value":"4", "display":"Children's Music"}, {"value":"5", "display":"Classical"}, {"value":"6", "display":"Country"},
+{"value":"50", "display":"Fitness & Workout"}, {"value":"18", "display":"Hip Hop/Rap"}, {"value":"8", "display":"Holiday"},
+{"value":"22", "display":"Christian & Gospel"}, {"value":"11", "display":"Jazz"}, {"value":"14", "display":"Pop"}, {"value":"15", "display":"R&B/Soul"}, {"value":"21", "display":"Rock"},
+{"value":"10", "display":"Singer/Songwriter"}, {"value":"16", "display":"Soundtrack"}, {"value":"23", "display":"Vocal"}, {"value":"19", "display":"World"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topalbums/sf=143460/", "display":"Top Albums", "name":"topalbums"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topimixes/sf=143460/", "display":"Top iMixes", "name":"topimixes"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topsongs/sf=143460/", "display":"Top Songs", "name":"topsongs"},
+{"urlSuffix":"rss.xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStore.woa/wpa/MRSS/newreleases/sf=143460/", "display":"New Releases", "name":"newreleases"},
+{"urlSuffix":"rss.xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStore.woa/wpa/MRSS/justadded/sf=143460/", "display":"Just Added", "name":"justadded"},
+{"urlSuffix":"rss.xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStore.woa/wpa/MRSS/featuredalbums/sf=143460/", "display":"Featured Albums & Exclusives", "name":"featuredalbums"}]}, "display":"Music", "name":"Music", "canBeExplicit":true},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}, {"value":"1301", "display":"Arts"}, {"value":"1321", "display":"Business"}, {"value":"1303", "display":"Comedy"}, {"value":"1304", "display":"Education"},
+{"value":"1323", "display":"Games & Hobbies"},
+{"value":"1325", "display":"Government & Organizations"}, {"value":"1307", "display":"Health"},
+{"value":"1305", "display":"Kids & Family"}, {"value":"1310", "display":"Music"},
+{"value":"1311", "display":"News & Politics"},
+{"value":"1314", "display":"Religion & Spirituality"},
+{"value":"1315", "display":"Science & Medicine"},
+{"value":"1324", "display":"Society & Culture"},
+{"value":"1316", "display":"Sports & Recreation"}, {"value":"1318", "display":"Technology"}, {"value":"1309", "display":"TV & Film"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppodcasts/sf=143460/", "display":"Top Podcasts", "name":"toppodcasts"}]}, "display":"Podcasts", "name":"Podcasts", "canBeExplicit":true},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"},
+{"value":"50000041", "display":"Arts & Entertainment"},
+{"value":"50000070", "display":"Audiobooks Latino"},
+{"value":"50000042", "display":"Biography & Memoir"},
+{"value":"50000043", "display":"Business"},
+{"value":"50000045", "display":"Classics"}, {"value":"50000046", "display":"Comedy"},
+{"value":"50000047", "display":"Drama & Poetry"},
+{"value":"50000040", "display":"Fiction"},
+{"value":"50000049", "display":"History"},
+{"value":"50000044", "display":"Kids & Young Adults"},
+{"value":"50000050", "display":"Languages"},
+{"value":"50000051", "display":"Mystery"}, {"value":"74", "display":"News"},
+{"value":"50000052", "display":"Nonfiction"},
+{"value":"75", "display":"Programs & Performances"},
+{"value":"50000053", "display":"Religion & Spirituality"},
+{"value":"50000069", "display":"Romance"},
+{"value":"50000055", "display":"Sci-Fi & Fantasy"},
+{"value":"50000054", "display":"Science"},
+{"value":"50000056", "display":"Self Development"},
+{"value":"50000048", "display":"Speakers & Storytellers"}, {"value":"50000057", "display":"Sports"},
+{"value":"50000058", "display":"Technology"},
+{"value":"50000059", "display":"Travel & Adventure"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topaudiobooks/sf=143460/", "display":"Top Audiobooks", "name":"topaudiobooks"}]}, "display":"Audiobooks", "name":"Audiobooks", "canBeExplicit":true},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toptvepisodes/sf=143460/", "display":"Top TV Episodes", "name":"toptvepisodes"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toptvseasons/sf=143460/", "display":"Top TV Seasons", "name":"toptvseasons"}]}, "display":"TV Shows", "name":"TV Shows", "canBeExplicit":false},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topmusicvideos/sf=143460/", "display":"Top Music Videos", "name":"topmusicvideos"}]}, "display":"Music Videos", "name":"Music Videos", "canBeExplicit":true},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topmovies/sf=143460/", "display":"Top Movies", "name":"topmovies"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topvideorentals/sf=143460/", "display":"Top Video Rentals", "name":"topvideorentals"}]}, "display":"Movies", "name":"Movies", "canBeExplicit":false},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}, {"value":"6018", "display":"Books"}, {"value":"6000", "display":"Business"}, {"value":"6017", "display":"Education"},
+{"value":"6016", "display":"Entertainment"}, {"value":"6015", "display":"Finance"}, {"value":"6014", "display":"Games"},
+{"value":"6013", "display":"Healthcare & Fitness"}, {"value":"6012", "display":"Lifestyle"}, {"value":"6020", "display":"Medical"}, {"value":"6011", "display":"Music"}, {"value":"6010", "display":"Navigation"}, {"value":"6009", "display":"News"},
+{"value":"6008", "display":"Photography"},
+{"value":"6007", "display":"Productivity"}, {"value":"6006", "display":"Reference"},
+{"value":"6005", "display":"Social Networking"}, {"value":"6004", "display":"Sports"}, {"value":"6003", "display":"Travel"}, {"value":"6002", "display":"Utilities"}, {"value":"6001", "display":"Weather"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topfreeapplications/sf=143460/", "display":"Top Free Apps", "name":"topfreeapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppaidapplications/sf=143460/", "display":"Top Paid Apps", "name":"toppaidapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topgrossingapplications/sf=143460/", "display":"Top Grossing Apps", "name":"topgrossingapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topfreeipadapplications/sf=143460/", "display":"Top Free iPad Apps", "name":"topfreeipadapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppaidipadapplications/sf=143460/", "display":"Top Paid iPad Apps", "name":"toppaidipadapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topgrossingipadapplications/sf=143460/", "display":"Top Grossing iPad Apps", "name":"topgrossingipadapplications"}]}, "display":"Apps", "name":"Mobile Software Applications", "canBeExplicit":false}]}
View
23 public/javascripts/wsAvailableFeeds/BR.js
@@ -0,0 +1,23 @@
+availableFeeds={"display":"Media Type", "name":"mediaType", "list":[
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}, {"value":"1301", "display":"Arts"}, {"value":"1321", "display":"Business"}, {"value":"1303", "display":"Comedy"}, {"value":"1304", "display":"Education"},
+{"value":"1323", "display":"Games & Hobbies"},
+{"value":"1325", "display":"Government & Organizations"}, {"value":"1307", "display":"Health"},
+{"value":"1305", "display":"Kids & Family"}, {"value":"1310", "display":"Music"},
+{"value":"1311", "display":"News & Politics"},
+{"value":"1314", "display":"Religion & Spirituality"},
+{"value":"1315", "display":"Science & Medicine"},
+{"value":"1324", "display":"Society & Culture"},
+{"value":"1316", "display":"Sports & Recreation"}, {"value":"1318", "display":"Technology"}, {"value":"1309", "display":"TV & Film"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppodcasts/sf=143503/", "display":"Top Podcasts", "name":"toppodcasts"}]}, "display":"Podcasts", "name":"Podcasts", "canBeExplicit":true},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}, {"value":"6018", "display":"Books"}, {"value":"6000", "display":"Business"}, {"value":"6017", "display":"Education"},
+{"value":"6016", "display":"Entertainment"}, {"value":"6015", "display":"Finance"}, {"value":"6014", "display":"Games"},
+{"value":"6013", "display":"Healthcare & Fitness"}, {"value":"6012", "display":"Lifestyle"}, {"value":"6020", "display":"Medical"}, {"value":"6011", "display":"Music"}, {"value":"6010", "display":"Navigation"}, {"value":"6009", "display":"News"},
+{"value":"6008", "display":"Photography"},
+{"value":"6007", "display":"Productivity"}, {"value":"6006", "display":"Reference"},
+{"value":"6005", "display":"Social Networking"}, {"value":"6004", "display":"Sports"}, {"value":"6003", "display":"Travel"}, {"value":"6002", "display":"Utilities"}, {"value":"6001", "display":"Weather"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topfreeapplications/sf=143503/", "display":"Top Free Apps", "name":"topfreeapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppaidapplications/sf=143503/", "display":"Top Paid Apps", "name":"toppaidapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topgrossingapplications/sf=143503/", "display":"Top Grossing Apps", "name":"topgrossingapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topfreeipadapplications/sf=143503/", "display":"Top Free iPad Apps", "name":"topfreeipadapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppaidipadapplications/sf=143503/", "display":"Top Paid iPad Apps", "name":"toppaidipadapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topgrossingipadapplications/sf=143503/", "display":"Top Grossing iPad Apps", "name":"topgrossingipadapplications"}]}, "display":"Apps", "name":"Mobile Software Applications", "canBeExplicit":false}]}
View
75 public/javascripts/wsAvailableFeeds/US.js
@@ -0,0 +1,75 @@
+availableFeeds={"display":"Media Type", "name":"mediaType", "list":[
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}, {"value":"20", "display":"Alternative"}, {"value":"2", "display":"Blues"},
+{"value":"4", "display":"Children's Music"},
+{"value":"22", "display":"Christian & Gospel"}, {"value":"5", "display":"Classical"}, {"value":"3", "display":"Comedy"}, {"value":"6", "display":"Country"}, {"value":"17", "display":"Dance"}, {"value":"7", "display":"Electronic"},
+{"value":"50", "display":"Fitness & Workout"}, {"value":"18", "display":"Hip Hop/Rap"}, {"value":"11", "display":"Jazz"}, {"value":"12", "display":"Latino"}, {"value":"14", "display":"Pop"}, {"value":"15", "display":"R&B/Soul"}, {"value":"24", "display":"Reggae"}, {"value":"21", "display":"Rock"},
+{"value":"10", "display":"Singer/Songwriter"}, {"value":"16", "display":"Soundtrack"},
+{"value":"50000061", "display":"Spoken Word"}, {"value":"19", "display":"World"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topalbums/sf=143441/", "display":"Top Albums", "name":"topalbums"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topimixes/sf=143441/", "display":"Top iMixes", "name":"topimixes"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topsongs/sf=143441/", "display":"Top Songs", "name":"topsongs"},
+{"urlSuffix":"rss.xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStore.woa/wpa/MRSS/newreleases/sf=143441/", "display":"New Releases", "name":"newreleases"},
+{"urlSuffix":"rss.xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStore.woa/wpa/MRSS/justadded/sf=143441/", "display":"Just Added", "name":"justadded"},
+{"urlSuffix":"rss.xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStore.woa/wpa/MRSS/featuredalbums/sf=143441/", "display":"Featured Albums & Exclusives", "name":"featuredalbums"}]}, "display":"Music", "name":"Music", "canBeExplicit":true},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}, {"value":"1301", "display":"Arts"}, {"value":"1321", "display":"Business"}, {"value":"1303", "display":"Comedy"}, {"value":"1304", "display":"Education"},
+{"value":"1323", "display":"Games & Hobbies"},
+{"value":"1325", "display":"Government & Organizations"}, {"value":"1307", "display":"Health"},
+{"value":"1305", "display":"Kids & Family"}, {"value":"1310", "display":"Music"},
+{"value":"1311", "display":"News & Politics"},
+{"value":"1314", "display":"Religion & Spirituality"},
+{"value":"1315", "display":"Science & Medicine"},
+{"value":"1324", "display":"Society & Culture"},
+{"value":"1316", "display":"Sports & Recreation"}, {"value":"1318", "display":"Technology"}, {"value":"1309", "display":"TV & Film"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppodcasts/sf=143441/", "display":"Top Podcasts", "name":"toppodcasts"}]}, "display":"Podcasts", "name":"Podcasts", "canBeExplicit":true},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"},
+{"value":"50000041", "display":"Arts & Entertainment"},
+{"value":"50000070", "display":"Audiobooks Latino"},
+{"value":"50000042", "display":"Biography & Memoir"},
+{"value":"50000043", "display":"Business"},
+{"value":"50000045", "display":"Classics"}, {"value":"50000046", "display":"Comedy"},
+{"value":"50000047", "display":"Drama & Poetry"},
+{"value":"50000040", "display":"Fiction"},
+{"value":"50000049", "display":"History"},
+{"value":"50000044", "display":"Kids & Young Adults"},
+{"value":"50000050", "display":"Languages"},
+{"value":"50000051", "display":"Mystery"}, {"value":"74", "display":"News"},
+{"value":"50000052", "display":"Nonfiction"},
+{"value":"75", "display":"Programs & Performances"},
+{"value":"50000053", "display":"Religion & Spirituality"},
+{"value":"50000069", "display":"Romance"},
+{"value":"50000055", "display":"Sci-Fi & Fantasy"},
+{"value":"50000054", "display":"Science"},
+{"value":"50000056", "display":"Self Development"},
+{"value":"50000048", "display":"Speakers & Storytellers"}, {"value":"50000057", "display":"Sports"},
+{"value":"50000058", "display":"Technology"},
+{"value":"50000059", "display":"Travel & Adventure"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topaudiobooks/sf=143441/", "display":"Top Audiobooks", "name":"topaudiobooks"}]}, "display":"Audiobooks", "name":"Audiobooks", "canBeExplicit":true},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}, {"value":"4002", "display":"Animation"}, {"value":"4004", "display":"Classic"}, {"value":"4000", "display":"Comedy"}, {"value":"4001", "display":"Drama"}, {"value":"4005", "display":"Kids"}, {"value":"4006", "display":"Nonfiction"}, {"value":"4007", "display":"Reality TV"},
+{"value":"4008", "display":"Sci-Fi & Fantasy"}, {"value":"4009", "display":"Sports"}, {"value":"4010", "display":"Teens"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toptvepisodes/sf=143441/", "display":"Top TV Episodes", "name":"toptvepisodes"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toptvseasons/sf=143441/", "display":"Top TV Seasons", "name":"toptvseasons"}]}, "display":"TV Shows", "name":"TV Shows", "canBeExplicit":false},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"},
+{"value":"1620", "display":"Alternative"}, {"value":"1606", "display":"Country"}, {"value":"1607", "display":"Electronic"},
+{"value":"1618", "display":"Hip Hop/Rap"}, {"value":"1612", "display":"Latino"}, {"value":"1614", "display":"Pop"}, {"value":"1615", "display":"R&B/Soul"}, {"value":"1621", "display":"Rock"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topmusicvideos/sf=143441/", "display":"Top Music Videos", "name":"topmusicvideos"}]}, "display":"Music Videos", "name":"Music Videos", "canBeExplicit":true},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"},
+{"value":"4401", "display":"Action & Adventure"}, {"value":"4403", "display":"Classics"}, {"value":"4404", "display":"Comedy"},
+{"value":"4405", "display":"Documentary"}, {"value":"4406", "display":"Drama"}, {"value":"4408", "display":"Horror"},
+{"value":"4409", "display":"Independent"},
+{"value":"4410", "display":"Kids & Family"}, {"value":"4412", "display":"Romance"},
+{"value":"4413", "display":"Sci-Fi & Fantasy"},
+{"value":"4414", "display":"Short Films"}, {"value":"4417", "display":"Sports"}, {"value":"4416", "display":"Thriller"}, {"value":"4418", "display":"Western"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topmovies/sf=143441/", "display":"Top Movies", "name":"topmovies"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topvideorentals/sf=143441/", "display":"Top Video Rentals", "name":"topvideorentals"}]}, "display":"Movies", "name":"Movies", "canBeExplicit":false},
+{"genres":{"display":"Genre", "list":[{"value":"", "display":"All Genres"}, {"value":"6018", "display":"Books"}, {"value":"6000", "display":"Business"}, {"value":"6017", "display":"Education"},
+{"value":"6016", "display":"Entertainment"}, {"value":"6015", "display":"Finance"}, {"value":"6014", "display":"Games"},
+{"value":"6013", "display":"Healthcare & Fitness"}, {"value":"6012", "display":"Lifestyle"}, {"value":"6020", "display":"Medical"}, {"value":"6011", "display":"Music"}, {"value":"6010", "display":"Navigation"}, {"value":"6009", "display":"News"},
+{"value":"6008", "display":"Photography"},
+{"value":"6007", "display":"Productivity"}, {"value":"6006", "display":"Reference"},
+{"value":"6005", "display":"Social Networking"}, {"value":"6004", "display":"Sports"}, {"value":"6003", "display":"Travel"}, {"value":"6002", "display":"Utilities"}, {"value":"6001", "display":"Weather"}], "key":"genre"}, "types":{"display":"Feed Type", "list":[
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topfreeapplications/sf=143441/", "display":"Top Free Apps", "name":"topfreeapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppaidapplications/sf=143441/", "display":"Top Paid Apps", "name":"toppaidapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topgrossingapplications/sf=143441/", "display":"Top Grossing Apps", "name":"topgrossingapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topfreeipadapplications/sf=143441/", "display":"Top Free iPad Apps", "name":"topfreeipadapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppaidipadapplications/sf=143441/", "display":"Top Paid iPad Apps", "name":"toppaidipadapplications"},
+{"urlSuffix":"xml", "urlPrefix":"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topgrossingipadapplications/sf=143441/", "display":"Top Grossing iPad Apps", "name":"topgrossingipadapplications"}]}, "display":"Apps", "name":"Mobile Software Applications", "canBeExplicit":false}]}
View
19 views/itunes_rss.erb
@@ -71,16 +71,16 @@
</div>
<div id="field_mediatype" class="rssgen_field">
<label>Media Type</label>
- <select id="feedMediaType" disabled></select>
+ <select id="feedMediaType" disabled="disabled"></select>
</div>
<div id="field_feedtype" class="rssgen_field">
<label>Feed Type</label>
- <select id="feedType" disabled></select>
+ <select id="feedType" disabled="disabled"></select>
</div>
<div id="field_size" class="rssgen_field">
<label>Size</label>
- <select id="feedSize" style="width:60px" disabled>
- <option value="10" selected>10</option>
+ <select id="feedSize" style="width:60px" disabled="disabled">
+ <option value="10" selected="selected">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
@@ -89,13 +89,14 @@
</div>
<div id="field_genre" class="rssgen_field">
<label>Genre</label>
- <select id="feedGenre" disabled></select>
+ <select id="feedGenre" disabled="disabled"></select>
</div>
<div id="field_explicit" class="rssgen_field" style="display:none;margin:0;">
<label>Explicit Content</label>
- <input type="radio" value="true" name="feedEC" id="feedECYes "/> <label for="feedECYes">Yes</label>
- &nbsp;&nbsp;&nbsp;
- <input type="radio" value="false" name="feedEC" id="feedECNo "/> <label for="feedECNo">No</label>
+ <select id="feedEC">
+ <option value="true" selected="selected">Explicit</option>
+ <option value="false">Censored</option>
+ </select>
</div>
<div id="generate_rss">
<input style="vertical-align:bottom" id="generate_btn" type="button" value="Generate"></input>
@@ -105,7 +106,7 @@
<div class="clear">&nbsp;</div>
<div id="urlOutput" style="display:none">
<label>RSS Feed URL</label><br/>
- <textarea id="urlField"></textarea>
+ <input id="urlField" value="" />
<div id="preview_rss"><input type="button" id="preview_btn" value="Preview"></input></div>
<div class="clear">&nbsp;</div>
</div>
View
1 views/layout.erb
@@ -26,7 +26,6 @@
<%= yield %>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
- <!-- <script src="/javascripts/jquery-1.4.2.js" type="text/javascript"></script> -->
<script src="/javascripts/application.js" type="text/javascript"></script>
<script type="text/javascript">
jQuery(document).ready(function($){
View
4 views/partials/itunes_rss/_javascripts.erb
@@ -1,5 +1,9 @@
+<script src="/javascripts/jquery.ba-getobject.min.js" type="text/javascript"></script>
+<script src="/javascripts/jquery.ba-bbq.min.js" type="text/javascript"></script>
+<!--
<script src="http://ax.itunes.apple.com/javascript/prototype.js" type="text/javascript"></script>
<script src="/javascripts/itunes_rss_wsAvailableFeeds.js" type="text/javascript"></script>
+-->
<script src="/javascripts/itunes_rss.js" type="text/javascript"></script>
<script type="text/javascript">
jQuery(document).ready(function($){

0 comments on commit 24160ea

Please sign in to comment.
Something went wrong with that request. Please try again.