Refactor code structure for improved readability and maintainability

This commit is contained in:
2025-04-10 19:23:03 +07:00
parent e4705579f0
commit 0700a715e4
5693 changed files with 857475 additions and 0 deletions

View File

@ -0,0 +1,20 @@
Copyright (c) 2012 Digital Fusion, http://teamdf.com/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,430 @@
/**
* jQuery list plug-in 1.2.1
* Copyright 2012, Digital Fusion
* Licensed under the MIT license.
* http://teamdf.com/jquery-plugins/license/
*
* @author Sam Sehnert, Phil Taylor
*/
(function($){
"use strict";
// The name of your plugin. This is used to namespace your
// plugin methods, object data, and registerd events.
var plugin_name = 'list';
var plugin_version = '1.2.1';
var plugin_logging = true;
// Set up the plugin defaults.
// These will be stored in $this.data(plugin_name).settings,
// and can be overwritten by having 'options' passed through
// as the parameter to the init method.
var defaults = {
headerSelector : 'dt',
zIndex : 1
};
var scrollTimeout = null;
// Any private methods that the plugin uses, such as event handlers,
// or small utility functions for parsing data etc that isn't useful
// outside the context of the plugin code itself.
var _private = {
log : function(){
// SAFELY call console.log without fear of errors
// also provides an override for turning off all plugin console output.
if( plugin_logging && window.console && window.console.log ){
try {
// IE 8 doesn't implement apply on the console methods.
window.console.log.apply(console,arguments);
} catch (e) {
// Because IE8 doesn't implement apply for console methods,
// we simply pass the arguments directly to the log.
window.console.log( arguments );
}
}
},
// Contains events for this plugin.
events : {
/**
* Window resize (should also be called when resizing the target element).
*/
resize : function(){
var $this = $(this),data = $this.data(plugin_name);
if( data ){
data.fakeHeader.width(data.headers.width());
data.wrapper.css('maxHeight',$this.css('maxHeight'));
}
},
/**
* List element scroll handler event. Called to animate and substitute heading blocks.
*/
scroll : function(){
var $this = $(this),data = $this.data(plugin_name);
if( data ){
var newHeader = null,
currentHeader = data.headers.eq( data.currentHeader ),
nextHeader = data.currentHeader >= data.headers.length-1 ? null : data.headers.eq( data.currentHeader+1 ),
prevHeader = data.currentHeader <= 0 ? null : data.headers.eq( data.currentHeader-1 ),
trigger = false;
// Make sure the container top position is fresh.
data.containerTop = $this.offset().top + parseInt($this.css('marginTop'),10) + parseInt($this.css('borderTopWidth'),10);
data.fakeHeader.css('top',0);
// Check the position of the current header rather than the previous header.
if( prevHeader !== null ){
var top = currentHeader.offset().top,
height = currentHeader.outerHeight();
if( top > data.containerTop ){
data.fakeHeader.css('top',(top-height)-data.containerTop);
data.fakeHeader.html(prevHeader.html());
data.currentHeader = data.currentHeader-1;
trigger = true;
}
if( (top-height) > data.containerTop ){
data.fakeHeader.css('top',0);
newHeader = data.currentHeader-1;
}
}
// Check the position of the next header element.
if( nextHeader !== null ){
var top = nextHeader.offset().top,
height = nextHeader.outerHeight();
if( (top-height) < data.containerTop ){
data.fakeHeader.css('top',(top-height)-data.containerTop);
}
if( top < data.containerTop ){
data.fakeHeader.css('top',0);
newHeader = data.currentHeader+1;
}
}
// Now assign the contents of the previous header.
if( newHeader !== null ){
var $header = data.headers.eq(newHeader);
data.currentHeader = newHeader;
data.fakeHeader.html($header.html());
trigger = true;
}
var max = ( data.wrapper.scrollTop() >= data.wrapper.prop('scrollHeight') - data.wrapper.height() );
if( trigger || max || data.max && !max ){
// Trigger the headingChange event.
$this.trigger('headingChange',[data.currentHeader,data.headers.eq(data.currentHeader),max]);
}
data.max = max;
// Save the new data.
$this.data(plugin_name,data);
}
}
}
}
// The methods array will allow you to define public methods that
// can be called using the plugin function using the following syntax;
//
// $('.selector').plugin_name( 'my_method'/*, optional arguments */);
//
// The 'init' method is special, and will be called when the user calls;
//
// $('.selector').plugin_name(/*{ options object }*/);
var methods = {
/**
* Initialises the plugin.
*
* @param options object : An object containing any overrides to the default settings.
*
* @return collection : Returns the jQuery collection
*/
init : function( options ){
// Loop through each passed element.
return $(this).each(function(){
// Settings to the defaults.
var settings = $.extend({},defaults);
// If options exist, lets merge them
// with our default settings.
if( typeof options == 'object' ) $.extend( settings, options );
// Create shortcuts, and get any existing data.
var $this = $(this), data = $this.data(plugin_name);
// If the plugin hasn't been initialized yet
if ( ! data ) {
// Create the data object.
data = {
target : $this, // This element.
wrapper : $this.wrapInner('<div class="ui-'+plugin_name+'" />').find('.ui-'+plugin_name+''),
settings : settings, // The settings for this plugin.
headers : [],
containerTop : 0,
currentHeader : 0,
fakeHeader : null,
scrolllist : [],
original : {
position : '',
overflowX : '',
overflowY : ''
},
max : false
}
// Add the container class, and the base HTML structure
$this.addClass('-'+plugin_name+'-container').css({
position : $this.css('position') == 'absolute' ? 'absolute' : 'relative',
overflowY : 'hidden'
});
// Grab some variables to set up the list.
data.headers = $this.find(data.settings.headerSelector);
data.fakeHeader = data.headers.eq(0).clone().removeAttr('id').addClass('-'+plugin_name+'-fakeheader').replaceWith('<div class="-'+plugin_name+'-fakeheader">'+data.headers.eq(0).html()+'</div>');
// bind a scroll event and change the text of the fake heading
data.wrapper.bind('scroll.'+plugin_name,$.proxy(_private.events.scroll,$this)).css({
height : '100%',
maxHeight : $this.css('maxHeight'),
overflowY : 'scroll',
position : 'relative'
});
// Set the fake headers
data.fakeHeader.css({
position : 'absolute',
top : 0,
width : data.headers.width(),
zIndex : data.settings.zIndex
});
// Bind the resize event to the window.
$(window).bind('resize.'+plugin_name,$.proxy(_private.events.resize,$this));
// Add the fake header before all other children, and set the HTML.
$this.data(plugin_name,data).prepend( data.fakeHeader );
}
});
},
/**
* Retrieves the current header index that the user is scrolled to.
*
* @return int : The index position of the header (relative to the headers collection).
*/
header : function(){
var $this = $(this),
data = $this.data(plugin_name);
// Only bother if we've set this up before.
if( data ){
return data.currentHeader;
}
},
/**
* Used to scroll to a new header element, or to retrieve the currently set header.
*
* @param int newHeader : The index position of the header (relative to the headers collection).
* @param mixed speed : The animation speed of scrolling to the new header.
* @param mixed easing : The animation easing to use.
* @param function completion : The animation completion function to call.
*
* @return collection : The collection that this was called with
*/
scrollTo : function( newHeader, speed, easing, completion ){
return this.each(function(){
var $this = $(this),
data = $this.data(plugin_name);
// Only bother if we've set this up before.
if( data ){
// If we've got the header, and its a number
if( newHeader !== undefined && !isNaN( newHeader ) && newHeader >= 0 && newHeader < data.headers.length ){
// Get the new header.
var $header = data.headers.eq(newHeader),
borderHeight = $header.outerHeight() - $header.height(),
scrollTo = $header.position().top + data.wrapper.scrollTop() + borderHeight;
// If we're not animating, we need to set the element directly.
if( !speed ){
data.wrapper.stop().scrollTop( scrollTo );
// Set as the current header.
data.currentHeader = newHeader;
data.fakeHeader.html($header.html());
// Trigger the headingChange event.
$this.trigger('headingChange',[newHeader,$header]);
// Store the new header data.
$this.data(plugin_name,data);
} else {
// If we are animating, the scroll event will fire.
data.wrapper.stop().animate({scrollTop:scrollTo},speed,easing,completion);
}
}
}
});
},
/**
* Used to modify settings after initialisation has taken place.
* an example switch construct has been written to show how you
* might fire off an update procedure for certain defaults.
* Should only be called on one element at a time.
*
* @param key string : The option name that you want to update.
* @param value mixed : (opt) The value that you want to set the option to.
*
* @return mixed : If no value is passed, will return the value for the passed key, otherwise, returns the jQuery collection.
*/
option : function( key, value ){
var $this = $(this),
data = $this.data(plugin_name);
// Only bother if we've set this up before.
if( data ){
// Return settings array if no key is provided.
if( typeof key == 'undefined' ) return data.settings;
// The key has to exist, otherwise its invalid.
if( !key in data.settings ) return false;
// Check if we're adding or updating.
if( typeof value == 'undefined' ){
return data.settings[key];
} else {
data.settings[key] = value;
return $this;
}
}
},
/**
* Get the current name and version number of this plugin.
*
* @param num bool : Whether to return the version number, or string.
*
* @return string | number : The version string or version number.
*/
version : function( num ){
// Returns the version string for this plugin.
if( num ){
// Calculate the version number.
var v = plugin_version.split('.'),
major = ( Number( v[0] ) || 1 )+'',
minor = ( Number( v[1] ) || 0 )+'',
bugfix = ( Number( v[2] ) || 0 )+'',
fill = '000';
// Return the version as a comparable number.
return Number( fill.slice(0,3-major.length)+major+fill.slice(0,3-minor.length)+minor+fill.slice(0,3-bugfix.length)+bugfix );
} else {
// Return the version string for this plugin.
return plugin_name+' v'+plugin_version;
}
},
/**
* Remove all data and events associated with the plugin, and restore
* the status of any manipulated elmenets to pre-plugin state.
*
* @return collection : Returns the jQuery collection.
*/
destroy: function(){
/* Remove the ui plugin from these elements that have it */
return this.each(function(){
var $this = $(this),
data = $this.data(plugin_name);
// Only bother if we've set this up before.
if( data ){
// Remove wrapper and fakeheader.
data.wrapper.children().unwrap();
data.fakeHeader.remove();
// Now, remove all data, etc, then
// reattach this element to its parent, then delete list div.
$this.css(data.original)
.removeData(plugin_name)
.removeClass('-'+plugin_name+'-container')
.unbind('.'+plugin_name);
}
});
}
};
/**
* Plugin method calling handler.
*
* @param method string : (opt) Calls the defined method (or init function if omitted).
* @param arguments : Any remaining arguments will be passed as arguments to the recieving method.
*
* @return mixed : Returns the result of the called method.
*/
$.fn[plugin_name] = function( method ){
// Method calling logic
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.' + plugin_name );
}
}
// Initialise $.plugin_name for methods below.
$[plugin_name] = {};
/**
* Allow console logging from this plugin?
*
* @param l bool : (opt) Turn logging on or off...
*
* @return bool : Whether this plugin will print to the log or not.
*/
$[plugin_name].log = function(l){ if(l!==undefined){ plugin_logging=l; } return plugin_logging; };
})(jQuery);

View File

@ -0,0 +1 @@
;(function(e){var k=!0,l={headerSelector:"dt",zIndex:1},m=function(){var b=e(this),a=b.data("list");a&&(a.fakeHeader.width(a.headers.width()),a.wrapper.css("maxHeight",b.css("maxHeight")))},n=function(){var b=e(this),a=b.data("list");if(a){var d=null,c=a.headers.eq(a.currentHeader),i=a.currentHeader>=a.headers.length-1?null:a.headers.eq(a.currentHeader+1),f=0>=a.currentHeader?null:a.headers.eq(a.currentHeader-1),h=!1;a.containerTop=b.offset().top+parseInt(b.css("marginTop"),10)+parseInt(b.css("borderTopWidth"), 10);a.fakeHeader.css("top",0);if(null!==f){var g=c.offset().top,c=c.outerHeight();g>a.containerTop&&(a.fakeHeader.css("top",g-c-a.containerTop),a.fakeHeader.html(f.html()),a.currentHeader-=1,h=!0);g-c>a.containerTop&&(a.fakeHeader.css("top",0),d=a.currentHeader-1)}null!==i&&(g=i.offset().top,c=i.outerHeight(),g-c<a.containerTop&&a.fakeHeader.css("top",g-c-a.containerTop),g<a.containerTop&&(a.fakeHeader.css("top",0),d=a.currentHeader+1));null!==d&&(h=a.headers.eq(d),a.currentHeader=d,a.fakeHeader.html(h.html()), h=!0);d=a.wrapper.scrollTop()>=a.wrapper.prop("scrollHeight")-a.wrapper.height();(h||d||a.max&&!d)&&b.trigger("headingChange",[a.currentHeader,a.headers.eq(a.currentHeader),d]);a.max=d;b.data("list",a)}},j={init:function(b){return e(this).each(function(){var a=e.extend({},l);"object"==typeof b&&e.extend(a,b);var d=e(this),c=d.data("list");c||(c={target:d,wrapper:d.wrapInner('<div class="ui-list" />').find(".ui-list"),settings:a,headers:[],containerTop:0,currentHeader:0,fakeHeader:null,scrolllist:[], original:{position:"",overflowX:"",overflowY:""},max:!1},d.addClass("-list-container").css({position:"absolute"==d.css("position")?"absolute":"relative",overflowY:"hidden"}),c.headers=d.find(c.settings.headerSelector),c.fakeHeader=c.headers.eq(0).clone().removeAttr("id").addClass("-list-fakeheader").replaceWith('<div class="-list-fakeheader">'+c.headers.eq(0).html()+"</div>"),c.wrapper.bind("scroll.list",e.proxy(n,d)).css({height:"100%",maxHeight:d.css("maxHeight"),overflowY:"scroll",position:"relative"}), c.fakeHeader.css({position:"absolute",top:0,width:c.headers.width(),zIndex:c.settings.zIndex}),e(window).bind("resize.list",e.proxy(m,d)),d.data("list",c).prepend(c.fakeHeader))})},header:function(){var b=e(this).data("list");if(b)return b.currentHeader},scrollTo:function(b,a,d,c){return this.each(function(){var i=e(this),f=i.data("list");if(f&&void 0!==b&&!isNaN(b)&&0<=b&&b<f.headers.length){var h=f.headers.eq(b),g=h.outerHeight()-h.height(),g=h.position().top+f.wrapper.scrollTop()+g;a?f.wrapper.stop().animate({scrollTop:g}, a,d,c):(f.wrapper.stop().scrollTop(g),f.currentHeader=b,f.fakeHeader.html(h.html()),i.trigger("headingChange",[b,h]),i.data("list",f))}})},option:function(b,a){var d=e(this),c=d.data("list");if(c){if("undefined"==typeof b)return c.settings;if(!b in c.settings)return!1;if("undefined"==typeof a)return c.settings[b];c.settings[b]=a;return d}},version:function(b){if(b){var a=["1","2","1"],b=(Number(a[0])||1)+"",d=(Number(a[1])||0)+"",a=(Number(a[2])||0)+"";return Number("000".slice(0,3-b.length)+b+"000".slice(0, 3-d.length)+d+"000".slice(0,3-a.length)+a)}return"list v1.2.1"},destroy:function(){return this.each(function(){var b=e(this),a=b.data("list");a&&(a.wrapper.children().unwrap(),a.fakeHeader.remove(),b.css(a.original).removeData("list").removeClass("-list-container").unbind(".list"))})}};e.fn.list=function(b){if(j[b])return j[b].apply(this,Array.prototype.slice.call(arguments,1));if("object"===typeof b||!b)return j.init.apply(this,arguments);e.error("Method "+b+" does not exist on jQuery.list")};e.list= {};e.list.log=function(b){void 0!==b&&(k=b);return k}})(jQuery);