Owen Leonard
eb92d94be1
The goal of this theme is to provide a fully-responsive OPAC which offers a high level of functionality across multiple devices with varied viewport sizes. Its style is based on the CCSR theme, with elements of the Bootstrap framework providing default styling of buttons, menus, modals, etc. The Bootstrap grid is used everywhere, but Bootstrap's default responsive breakpoints have been expanded to allow for better flexibility for our needs. All non-translation-depended files are in the root directory of this new theme: css, images, itemtypeimg, js, less, and lib. Languages.pm has been modified to ignore the new directories when parsing the theme language directories. This theme introduces the use of LESS (http://lesscss.org/) to build CSS. Three LESS files can be found in the "less" directory: mixins.less, opac.less, and responsive.less. These three files are compiled into one CSS file for production: opac.css. "Base" theme styles are found in opac.less. A few "mixins" (http://lesscss.org/#-mixins) are found in mixins.less. Any CSS which is conditional on specific media queries is found in responsive.less. At the template level some general sturctural changes have been made. For the most part JavaScript is now at the end of each template as is recommended for performance reasons. JavaScript formerly in doc-head-close.inc is now in opac-bottom.inc. In order to be able to maintain this structure and accommodate page-specific scripts at the same time the use of BLOCK and PROCESS are added. By default opac-bottom.inc will PROCESS a "jsinclude" block: [% PROCESS jsinclude %] Each page template in the theme must contain this block, even if it is empty: [% BLOCK jsinclude %][% END %] Pages which require that page-specific JavaScript be inserted can add it to the jsinclude block and it will appear correctly at the bottom of the rendered page. The same is true for page-specific CSS. Each page contains a cssinclude block: [% BLOCK cssinclude %][% END %] ...which is processed in doc-head-close.inc: [% PROCESS cssinclude %] Using these methods helps us maintain a strict separation of CSS links and blocks (at the top of each page) and JavaScript (at the bottom). A few exceptions are made for some JavaScript which must be processed sooner: respond.js (https://github.com/scottjehl/Respond, conditionally applied to Internet Explorer versions < 9 to allow for layout responsiveness), the _() function required for JS translatability, and Modernizr (http://modernizr.com/, a script which detects browser features and allows us to conditionally load JavaScript based on available features--or lack thereof). Another new JavaScript dependency in this theme is enquire.js (http://wicky.nillia.ms/enquire.js/), which lets us trigger JavaScript events based on viewport size. I have made an effort to re-indent the templates in a sane way, eliminating trailing spaces and tabs. However, I have not wrapped lines at a specific line length. In order to improve template legibility I have also tried to insert comments indicating the origin of closing tags like <div> or template directives like [% END %]: </div> <!-- / .container-fluid --> [% END # / IF ( OpacBrowseResults && busc ) %] TESTING Proper testing of this theme is no easy task: Every template has been touched. Each page should work reasonable well at a variety of screen dimensions. Pages should be tested under many conditions which are controlled by toggling OPAC system preferences on and off. A variety of devices, platforms, and browsers should be tested. Signed-off-by: Galen Charlton <gmc@esilibrary.com>
392 lines
16 KiB
JavaScript
392 lines
16 KiB
JavaScript
/*
|
|
### jQuery Star Rating Plugin v3.14 - 2012-01-26 ###
|
|
* Home: http://www.fyneworks.com/jquery/star-rating/
|
|
* Code: http://code.google.com/p/jquery-star-rating-plugin/
|
|
*
|
|
* Dual licensed under the MIT and GPL licenses:
|
|
* http://www.opensource.org/licenses/mit-license.php
|
|
* http://www.gnu.org/licenses/gpl.html
|
|
###
|
|
*/
|
|
|
|
/*# AVOID COLLISIONS #*/
|
|
;if(window.jQuery) (function($){
|
|
/*# AVOID COLLISIONS #*/
|
|
|
|
// IE6 Background Image Fix
|
|
if ($.browser.msie) try { document.execCommand("BackgroundImageCache", false, true)} catch(e) { };
|
|
// Thanks to http://www.visualjquery.com/rating/rating_redux.html
|
|
|
|
// plugin initialization
|
|
$.fn.rating = function(options){
|
|
if(this.length==0) return this; // quick fail
|
|
|
|
// Handle API methods
|
|
if(typeof arguments[0]=='string'){
|
|
// Perform API methods on individual elements
|
|
if(this.length>1){
|
|
var args = arguments;
|
|
return this.each(function(){
|
|
$.fn.rating.apply($(this), args);
|
|
});
|
|
};
|
|
// Invoke API method handler
|
|
$.fn.rating[arguments[0]].apply(this, $.makeArray(arguments).slice(1) || []);
|
|
// Quick exit...
|
|
return this;
|
|
};
|
|
|
|
// Initialize options for this call
|
|
var options = $.extend(
|
|
{}/* new object */,
|
|
$.fn.rating.options/* default options */,
|
|
options || {} /* just-in-time options */
|
|
);
|
|
|
|
// Allow multiple controls with the same name by making each call unique
|
|
$.fn.rating.calls++;
|
|
|
|
// loop through each matched element
|
|
this
|
|
.not('.star-rating-applied')
|
|
.addClass('star-rating-applied')
|
|
.each(function(){
|
|
|
|
// Load control parameters / find context / etc
|
|
var control, input = $(this);
|
|
var eid = (this.name || 'unnamed-rating').replace(/\[|\]/g, '_').replace(/^\_+|\_+$/g,'');
|
|
var context = $(this.form || document.body);
|
|
|
|
// FIX: http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=23
|
|
var raters = context.data('rating');
|
|
if(!raters || raters.call!=$.fn.rating.calls) raters = { count:0, call:$.fn.rating.calls };
|
|
var rater = raters[eid];
|
|
|
|
// if rater is available, verify that the control still exists
|
|
if(rater) control = rater.data('rating');
|
|
|
|
if(rater && control)//{// save a byte!
|
|
// add star to control if rater is available and the same control still exists
|
|
control.count++;
|
|
|
|
//}// save a byte!
|
|
else{
|
|
// create new control if first star or control element was removed/replaced
|
|
|
|
// Initialize options for this rater
|
|
control = $.extend(
|
|
{}/* new object */,
|
|
options || {} /* current call options */,
|
|
($.metadata? input.metadata(): ($.meta?input.data():null)) || {}, /* metadata options */
|
|
{ count:0, stars: [], inputs: [] }
|
|
);
|
|
|
|
// increment number of rating controls
|
|
control.serial = raters.count++;
|
|
|
|
// create rating element
|
|
rater = $('<span class="star-rating-control"/>');
|
|
input.before(rater);
|
|
|
|
// Mark element for initialization (once all stars are ready)
|
|
rater.addClass('rating-to-be-drawn');
|
|
|
|
// Accept readOnly setting from 'disabled' property
|
|
if(input.attr('disabled') || input.hasClass('disabled')) control.readOnly = true;
|
|
|
|
// Accept required setting from class property (class='required')
|
|
if(input.hasClass('required')) control.required = true;
|
|
|
|
// Create 'cancel' button
|
|
rater.append(
|
|
control.cancel = $('<div class="rating-cancel"><a title="' + control.cancel + '">' + control.cancelValue + '</a></div>')
|
|
.mouseover(function(){
|
|
$(this).rating('drain');
|
|
$(this).addClass('star-rating-hover');
|
|
//$(this).rating('focus');
|
|
})
|
|
.mouseout(function(){
|
|
$(this).rating('draw');
|
|
$(this).removeClass('star-rating-hover');
|
|
//$(this).rating('blur');
|
|
})
|
|
.click(function(){
|
|
$(this).rating('select');
|
|
})
|
|
.data('rating', control)
|
|
);
|
|
|
|
}; // first element of group
|
|
|
|
// insert rating star
|
|
var star = $('<div class="star-rating rater-'+ control.serial +'"><a title="' + (this.title || this.value) + '">' + this.value + '</a></div>');
|
|
rater.append(star);
|
|
|
|
// inherit attributes from input element
|
|
if(this.id) star.attr('id', this.id);
|
|
if(this.className) star.addClass(this.className);
|
|
|
|
// Half-stars?
|
|
if(control.half) control.split = 2;
|
|
|
|
// Prepare division control
|
|
if(typeof control.split=='number' && control.split>0){
|
|
var stw = ($.fn.width ? star.width() : 0) || control.starWidth;
|
|
var spi = (control.count % control.split), spw = Math.floor(stw/control.split);
|
|
star
|
|
// restrict star's width and hide overflow (already in CSS)
|
|
.width(spw)
|
|
// move the star left by using a negative margin
|
|
// this is work-around to IE's stupid box model (position:relative doesn't work)
|
|
.find('a').css({ 'margin-left':'-'+ (spi*spw) +'px' })
|
|
};
|
|
|
|
// readOnly?
|
|
if(control.readOnly)//{ //save a byte!
|
|
// Mark star as readOnly so user can customize display
|
|
star.addClass('star-rating-readonly');
|
|
//} //save a byte!
|
|
else//{ //save a byte!
|
|
// Enable hover css effects
|
|
star.addClass('star-rating-live')
|
|
// Attach mouse events
|
|
.mouseover(function(){
|
|
$(this).rating('fill');
|
|
$(this).rating('focus');
|
|
})
|
|
.mouseout(function(){
|
|
$(this).rating('draw');
|
|
$(this).rating('blur');
|
|
})
|
|
.click(function(){
|
|
$(this).rating('select');
|
|
})
|
|
;
|
|
//}; //save a byte!
|
|
|
|
// set current selection
|
|
if(this.checked) control.current = star;
|
|
|
|
// set current select for links
|
|
if(this.nodeName=="A"){
|
|
if($(this).hasClass('selected'))
|
|
control.current = star;
|
|
};
|
|
|
|
// hide input element
|
|
input.hide();
|
|
|
|
// backward compatibility, form element to plugin
|
|
input.change(function(){
|
|
$(this).rating('select');
|
|
});
|
|
|
|
// attach reference to star to input element and vice-versa
|
|
star.data('rating.input', input.data('rating.star', star));
|
|
|
|
// store control information in form (or body when form not available)
|
|
control.stars[control.stars.length] = star[0];
|
|
control.inputs[control.inputs.length] = input[0];
|
|
control.rater = raters[eid] = rater;
|
|
control.context = context;
|
|
|
|
input.data('rating', control);
|
|
rater.data('rating', control);
|
|
star.data('rating', control);
|
|
context.data('rating', raters);
|
|
}); // each element
|
|
|
|
// Initialize ratings (first draw)
|
|
$('.rating-to-be-drawn').rating('draw').removeClass('rating-to-be-drawn');
|
|
|
|
return this; // don't break the chain...
|
|
};
|
|
|
|
/*--------------------------------------------------------*/
|
|
|
|
/*
|
|
### Core functionality and API ###
|
|
*/
|
|
$.extend($.fn.rating, {
|
|
// Used to append a unique serial number to internal control ID
|
|
// each time the plugin is invoked so same name controls can co-exist
|
|
calls: 0,
|
|
|
|
focus: function(){
|
|
var control = this.data('rating'); if(!control) return this;
|
|
if(!control.focus) return this; // quick fail if not required
|
|
// find data for event
|
|
var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
|
|
// focus handler, as requested by focusdigital.co.uk
|
|
if(control.focus) control.focus.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
|
|
}, // $.fn.rating.focus
|
|
|
|
blur: function(){
|
|
var control = this.data('rating'); if(!control) return this;
|
|
if(!control.blur) return this; // quick fail if not required
|
|
// find data for event
|
|
var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
|
|
// blur handler, as requested by focusdigital.co.uk
|
|
if(control.blur) control.blur.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
|
|
}, // $.fn.rating.blur
|
|
|
|
fill: function(){ // fill to the current mouse position.
|
|
var control = this.data('rating'); if(!control) return this;
|
|
// do not execute when control is in read-only mode
|
|
if(control.readOnly) return;
|
|
// Reset all stars and highlight them up to this element
|
|
this.rating('drain');
|
|
this.prevAll().andSelf().filter('.rater-'+ control.serial).addClass('star-rating-hover');
|
|
},// $.fn.rating.fill
|
|
|
|
drain: function() { // drain all the stars.
|
|
var control = this.data('rating'); if(!control) return this;
|
|
// do not execute when control is in read-only mode
|
|
if(control.readOnly) return;
|
|
// Reset all stars
|
|
control.rater.children().filter('.rater-'+ control.serial).removeClass('star-rating-on').removeClass('star-rating-hover');
|
|
},// $.fn.rating.drain
|
|
|
|
draw: function(){ // set value and stars to reflect current selection
|
|
var control = this.data('rating'); if(!control) return this;
|
|
// Clear all stars
|
|
this.rating('drain');
|
|
// Set control value
|
|
if(control.current){
|
|
control.current.data('rating.input').attr('checked','checked');
|
|
control.current.prevAll().andSelf().filter('.rater-'+ control.serial).addClass('star-rating-on');
|
|
}
|
|
else
|
|
$(control.inputs).removeAttr('checked');
|
|
// Show/hide 'cancel' button
|
|
control.cancel[control.readOnly || control.required?'hide':'show']();
|
|
// Add/remove read-only classes to remove hand pointer
|
|
this.siblings()[control.readOnly?'addClass':'removeClass']('star-rating-readonly');
|
|
},// $.fn.rating.draw
|
|
|
|
|
|
|
|
|
|
|
|
select: function(value,wantCallBack){ // select a value
|
|
|
|
// ***** MODIFICATION *****
|
|
// Thanks to faivre.thomas - http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=27
|
|
//
|
|
// ***** LIST OF MODIFICATION *****
|
|
// ***** added Parameter wantCallBack : false if you don't want a callback. true or undefined if you want postback to be performed at the end of this method'
|
|
// ***** recursive calls to this method were like : ... .rating('select') it's now like .rating('select',undefined,wantCallBack); (parameters are set.)
|
|
// ***** line which is calling callback
|
|
// ***** /LIST OF MODIFICATION *****
|
|
|
|
var control = this.data('rating'); if(!control) return this;
|
|
// do not execute when control is in read-only mode
|
|
if(control.readOnly) return;
|
|
// clear selection
|
|
control.current = null;
|
|
// programmatically (based on user input)
|
|
if(typeof value!='undefined'){
|
|
// select by index (0 based)
|
|
if(typeof value=='number')
|
|
return $(control.stars[value]).rating('select',undefined,wantCallBack);
|
|
// select by literal value (must be passed as a string
|
|
if(typeof value=='string')
|
|
//return
|
|
$.each(control.stars, function(){
|
|
if($(this).data('rating.input').val()==value) $(this).rating('select',undefined,wantCallBack);
|
|
});
|
|
}
|
|
else
|
|
control.current = this[0].tagName=='INPUT' ?
|
|
this.data('rating.star') :
|
|
(this.is('.rater-'+ control.serial) ? this : null);
|
|
|
|
// Update rating control state
|
|
this.data('rating', control);
|
|
// Update display
|
|
this.rating('draw');
|
|
// find data for event
|
|
var input = $( control.current ? control.current.data('rating.input') : null );
|
|
// click callback, as requested here: http://plugins.jquery.com/node/1655
|
|
|
|
// **** MODIFICATION *****
|
|
// Thanks to faivre.thomas - http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=27
|
|
//
|
|
//old line doing the callback :
|
|
//if(control.callback) control.callback.apply(input[0], [input.val(), $('a', control.current)[0]]);// callback event
|
|
//
|
|
//new line doing the callback (if i want :)
|
|
if((wantCallBack ||wantCallBack == undefined) && control.callback) control.callback.apply(input[0], [input.val(), $('a', control.current)[0]]);// callback event
|
|
//to ensure retro-compatibility, wantCallBack must be considered as true by default
|
|
// **** /MODIFICATION *****
|
|
|
|
},// $.fn.rating.select
|
|
|
|
|
|
|
|
|
|
|
|
readOnly: function(toggle, disable){ // make the control read-only (still submits value)
|
|
var control = this.data('rating'); if(!control) return this;
|
|
// setread-only status
|
|
control.readOnly = toggle || toggle==undefined ? true : false;
|
|
// enable/disable control value submission
|
|
if(disable) $(control.inputs).attr("disabled", "disabled");
|
|
else $(control.inputs).removeAttr("disabled");
|
|
// Update rating control state
|
|
this.data('rating', control);
|
|
// Update display
|
|
this.rating('draw');
|
|
},// $.fn.rating.readOnly
|
|
|
|
disable: function(){ // make read-only and never submit value
|
|
this.rating('readOnly', true, true);
|
|
},// $.fn.rating.disable
|
|
|
|
enable: function(){ // make read/write and submit value
|
|
this.rating('readOnly', false, false);
|
|
}// $.fn.rating.select
|
|
|
|
});
|
|
|
|
/*--------------------------------------------------------*/
|
|
|
|
/*
|
|
### Default Settings ###
|
|
eg.: You can override default control like this:
|
|
$.fn.rating.options.cancel = 'Clear';
|
|
*/
|
|
$.fn.rating.options = { //$.extend($.fn.rating, { options: {
|
|
cancel: 'Cancel Rating', // advisory title for the 'cancel' link
|
|
cancelValue: '', // value to submit when user click the 'cancel' link
|
|
split: 0, // split the star into how many parts?
|
|
|
|
// Width of star image in case the plugin can't work it out. This can happen if
|
|
// the jQuery.dimensions plugin is not available OR the image is hidden at installation
|
|
starWidth: 16//,
|
|
|
|
//NB.: These don't need to be pre-defined (can be undefined/null) so let's save some code!
|
|
//half: false, // just a shortcut to control.split = 2
|
|
//required: false, // disables the 'cancel' button so user can only select one of the specified values
|
|
//readOnly: false, // disable rating plugin interaction/ values cannot be changed
|
|
//focus: function(){}, // executed when stars are focused
|
|
//blur: function(){}, // executed when stars are focused
|
|
//callback: function(){}, // executed when a star is clicked
|
|
}; //} });
|
|
|
|
/*--------------------------------------------------------*/
|
|
|
|
/*
|
|
### Default implementation ###
|
|
The plugin will attach itself to file inputs
|
|
with the class 'multi' when the page loads
|
|
*/
|
|
$(function(){
|
|
$('input[type=radio].star').rating();
|
|
});
|
|
|
|
|
|
|
|
/*# AVOID COLLISIONS #*/
|
|
})(jQuery);
|
|
/*# AVOID COLLISIONS #*/
|