'
+ );
+ var els = $('a', nPaging);
+ $(els[0]).bind( 'click.DT', { action: "previous" }, fnClickHandler );
+ $(els[1]).bind( 'click.DT', { action: "next" }, fnClickHandler );
+ },
+
+ "fnUpdate": function ( oSettings, fnDraw ) {
+ var iListLength = 5;
+ var oPaging = oSettings.oInstance.fnPagingInfo();
+ var an = oSettings.aanFeatures.p;
+ var i, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2);
+
+ if ( oPaging.iTotalPages < iListLength) {
+ iStart = 1;
+ iEnd = oPaging.iTotalPages;
+ }
+ else if ( oPaging.iPage <= iHalf ) {
+ iStart = 1;
+ iEnd = iListLength;
+ } else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) {
+ iStart = oPaging.iTotalPages - iListLength + 1;
+ iEnd = oPaging.iTotalPages;
+ } else {
+ iStart = oPaging.iPage - iHalf + 1;
+ iEnd = iStart + iListLength - 1;
+ }
+
+ for ( i=0, iLen=an.length ; i'+j+'')
+ .insertBefore( $('li:last', an[i])[0] )
+ .bind('click', function (e) {
+ e.preventDefault();
+ oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength;
+ fnDraw( oSettings );
+ } );
+ }
+
+ // Add / remove disabled classes from the static elements
+ if ( oPaging.iPage === 0 ) {
+ $('li:first', an[i]).addClass('disabled');
+ } else {
+ $('li:first', an[i]).removeClass('disabled');
+ }
+
+ if ( oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0 ) {
+ $('li:last', an[i]).addClass('disabled');
+ } else {
+ $('li:last', an[i]).removeClass('disabled');
+ }
+ }
+ }
+ }
+} );
+
+
+/*
+ * TableTools Bootstrap compatibility
+ * Required TableTools 2.1+
+ */
+if ( $.fn.DataTable.TableTools ) {
+ // Set the classes that TableTools uses to something suitable for Bootstrap
+ $.extend( true, $.fn.DataTable.TableTools.classes, {
+ "container": "DTTT btn-group",
+ "buttons": {
+ "normal": "btn",
+ "disabled": "disabled"
+ },
+ "collection": {
+ "container": "DTTT_dropdown dropdown-menu",
+ "buttons": {
+ "normal": "",
+ "disabled": "disabled"
+ }
+ },
+ "print": {
+ "info": "DTTT_print_info modal"
+ },
+ "select": {
+ "row": "active"
+ }
+ } );
+
+ // Have the collection use a bootstrap compatible dropdown
+ $.extend( true, $.fn.DataTable.TableTools.DEFAULTS.oTags, {
+ "collection": {
+ "container": "ul",
+ "button": "li",
+ "liner": "a"
+ }
+ } );
+}
\ No newline at end of file
diff --git a/mall-master/src/main/resources/static/js/additional-methods.min.js b/mall-master/src/main/resources/static/js/additional-methods.min.js
new file mode 100644
index 0000000..94e500b
--- /dev/null
+++ b/mall-master/src/main/resources/static/js/additional-methods.min.js
@@ -0,0 +1,11 @@
+/*!
+ * jQuery Validation Plugin 1.11.1
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+ * http://docs.jquery.com/Plugins/Validation
+ *
+ * Copyright 2013 Jörn Zaefferer
+ * Released under the MIT license:
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function(){function a(b){return b.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," ").replace(/[.(),;:!?%#$'"_+=\/\-]*/g,"")}jQuery.validator.addMethod("maxWords",function(c,b,d){return this.optional(b)||a(c).match(/\b\w+\b/g).length<=d},jQuery.validator.format("Please enter {0} words or less."));jQuery.validator.addMethod("minWords",function(c,b,d){return this.optional(b)||a(c).match(/\b\w+\b/g).length>=d},jQuery.validator.format("Please enter at least {0} words."));jQuery.validator.addMethod("rangeWords",function(e,b,f){var d=a(e);var c=/\b\w+\b/g;return this.optional(b)||d.match(c).length>=f[0]&&d.match(c).length<=f[1]},jQuery.validator.format("Please enter between {0} and {1} words."))}());jQuery.validator.addMethod("letterswithbasicpunc",function(b,a){return this.optional(a)||/^[a-z\-.,()'"\s]+$/i.test(b)},"Letters or punctuation only please");jQuery.validator.addMethod("alphanumeric",function(b,a){return this.optional(a)||/^\w+$/i.test(b)},"Letters, numbers, and underscores only please");jQuery.validator.addMethod("lettersonly",function(b,a){return this.optional(a)||/^[a-z]+$/i.test(b)},"Letters only please");jQuery.validator.addMethod("nowhitespace",function(b,a){return this.optional(a)||/^\S+$/i.test(b)},"No white space please");jQuery.validator.addMethod("ziprange",function(b,a){return this.optional(a)||/^90[2-5]\d\{2\}-\d{4}$/.test(b)},"Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx");jQuery.validator.addMethod("zipcodeUS",function(b,a){return this.optional(a)||/\d{5}-\d{4}$|^\d{5}$/.test(b)},"The specified US ZIP Code is invalid");jQuery.validator.addMethod("integer",function(b,a){return this.optional(a)||/^-?\d+$/.test(b)},"A positive or negative non-decimal number please");jQuery.validator.addMethod("vinUS",function(o){if(o.length!==17){return false}var h,a,l,j,b,k;var c=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"];var m=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9];var g=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2];var e=0;for(h=0;h<17;h++){j=g[h];l=o.slice(h,h+1);if(h===8){k=l}if(!isNaN(l)){l*=j}else{for(a=0;a9&&a.match(/^(\+?1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/)},"Please specify a valid phone number");jQuery.validator.addMethod("phoneUK",function(a,b){a=a.replace(/\(|\)|\s+|-/g,"");return this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number");jQuery.validator.addMethod("mobileUK",function(a,b){a=a.replace(/\(|\)|\s+|-/g,"");return this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[45789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number");jQuery.validator.addMethod("phonesUK",function(a,b){a=a.replace(/\(|\)|\s+|-/g,"");return this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[45789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number");jQuery.validator.addMethod("postcodeUK",function(b,a){return this.optional(a)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(b)},"Please specify a valid UK postcode");jQuery.validator.addMethod("strippedminlength",function(b,a,c){return jQuery(b).text().length>=c},jQuery.validator.format("Please enter at least {0} characters"));jQuery.validator.addMethod("email2",function(b,a,c){return this.optional(a)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(b)},jQuery.validator.messages.email);jQuery.validator.addMethod("url2",function(b,a,c){return this.optional(a)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(b)},jQuery.validator.messages.url);jQuery.validator.addMethod("creditcardtypes",function(b,a,c){if(/[^0-9\-]+/.test(b)){return false}b=b.replace(/\D/g,"");var d=0;if(c.mastercard){d|=1}if(c.visa){d|=2}if(c.amex){d|=4}if(c.dinersclub){d|=8}if(c.enroute){d|=16}if(c.discover){d|=32}if(c.jcb){d|=64}if(c.unknown){d|=128}if(c.all){d=1|2|4|8|16|32|64|128}if(d&1&&/^(5[12345])/.test(b)){return b.length===16}if(d&2&&/^(4)/.test(b)){return b.length===16}if(d&4&&/^(3[47])/.test(b)){return b.length===15}if(d&8&&/^(3(0[012345]|[68]))/.test(b)){return b.length===14}if(d&16&&/^(2(014|149))/.test(b)){return b.length===15}if(d&32&&/^(6011)/.test(b)){return b.length===16}if(d&64&&/^(3)/.test(b)){return b.length===16}if(d&64&&/^(2131|1800)/.test(b)){return b.length===15}if(d&128){return true}return false},"Please enter a valid credit card number.");jQuery.validator.addMethod("ipv4",function(b,a,c){return this.optional(a)||/^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test(b)},"Please enter a valid IP v4 address.");jQuery.validator.addMethod("ipv6",function(b,a,c){return this.optional(a)||/^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(b)},"Please enter a valid IP v6 address.");jQuery.validator.addMethod("pattern",function(b,a,c){if(this.optional(a)){return true}if(typeof c==="string"){c=new RegExp("^(?:"+c+")$")}return c.test(b)},"Invalid format.");jQuery.validator.addMethod("require_from_group",function(g,f,d){var e=this;var b=d[1];var c=$(b,f.form).filter(function(){return e.elementValue(this)}).length>=d[0];if(!$(f).data("being_validated")){var a=$(b,f.form);a.data("being_validated",true);a.valid();a.data("being_validated",false)}return c},jQuery.format("Please fill at least {0} of these fields."));jQuery.validator.addMethod("skip_or_fill_minimum",function(h,e,i){var b=this,c=i[0],d=i[1];var g=$(d,e.form).filter(function(){return b.elementValue(this)}).length;var a=g>=c||g===0;if(!$(e).data("being_validated")){var f=$(d,e.form);f.data("being_validated",true);f.valid();f.data("being_validated",false)}return a},jQuery.format("Please either skip these fields or fill at least {0} of them."));jQuery.validator.addMethod("accept",function(e,c,g){var f=typeof g==="string"?g.replace(/\s/g,"").replace(/,/g,"|"):"image/*",d=this.optional(c),b,a;if(d){return d}if($(c).attr("type")==="file"){f=f.replace(/\*/g,".*");if(c.files&&c.files.length){for(b=0;b 1280 && $('body').hasClass('page-boxed') === false) {
+ $(".responsive").each(function () {
+ var forTablet = $(this).attr('data-tablet');
+ var forDesktop = $(this).attr('data-desktop');
+ if (forTablet) {
+ $(this).removeClass(forTablet);
+ $(this).addClass(forDesktop);
+ }
+ });
+ }
+ }
+
+ var handleSidebarState = function () {
+ // remove sidebar toggler if window width smaller than 900(for table and phone mode)
+ if ($(window).width() < 980) {
+ $('body').removeClass("page-sidebar-closed");
+ }
+ }
+
+ var runResponsiveHandlers = function () {
+ // reinitialize other subscribed elements
+ for (var i in responsiveHandlers) {
+ var each = responsiveHandlers[i];
+ each.call();
+ }
+ }
+
+ var handleResponsive = function () {
+ handleTooltips();
+ handleSidebarState();
+ handleDesktopTabletContents();
+ handleSidebarAndContentHeight();
+ handleChoosenSelect();
+ handleFixedSidebar();
+ runResponsiveHandlers();
+ }
+
+ var handleResponsiveOnInit = function () {
+ handleSidebarState();
+ handleDesktopTabletContents();
+ handleSidebarAndContentHeight();
+ }
+
+ var handleResponsiveOnResize = function () {
+ var resize;
+ if (isIE8) {
+ var currheight;
+ $(window).resize(function() {
+ if(currheight == document.documentElement.clientHeight) {
+ return; //quite event since only body resized not window.
+ }
+ if (resize) {
+ clearTimeout(resize);
+ }
+ resize = setTimeout(function() {
+ handleResponsive();
+ }, 50); // wait 50ms until window resize finishes.
+ currheight = document.documentElement.clientHeight; // store last body client height
+ });
+ } else {
+ $(window).resize(function() {
+ if (resize) {
+ clearTimeout(resize);
+ }
+ resize = setTimeout(function() {
+ console.log('resize');
+ handleResponsive();
+ }, 50); // wait 50ms until window resize finishes.
+ });
+ }
+ }
+
+ //* BEGIN:CORE HANDLERS *//
+ // this function handles responsive layout on screen size resize or mobile device rotate.
+
+ var handleSidebarAndContentHeight = function () {
+ var content = $('.page-content');
+ var sidebar = $('.page-sidebar');
+ var body = $('body');
+ var height;
+ //alert($(window).height());
+ if (body.hasClass("page-footer-fixed") === true && body.hasClass("page-sidebar-fixed") === false) {
+ var available_height = $(window).height() - $('.footer').height()-13;
+ if (content.height() < available_height) {
+ content.attr('style', 'min-height:' + available_height + 'px !important');
+ }
+ } else {
+ if (body.hasClass('page-sidebar-fixed')) {
+ height = _calculateFixedSidebarViewportHeight();
+
+ } else {
+ height = sidebar.height() + 20;
+ }
+ if (height >= content.height()) {
+ content.attr('style', 'min-height:' + height + 'px !important');
+ //$("#content").attr('style', 'height:100%;width:100%;');;
+
+ }
+ }
+ }
+
+ var handleSidebarMenu = function () {
+ jQuery('.page-sidebar').on('click', 'li > a', function (e) {
+ if ($(this).next().hasClass('sub-menu') == false) {
+ if ($('.btn-navbar').hasClass('collapsed') == false) {
+ $('.btn-navbar').click();
+ }
+ return;
+ }
+
+ var parent = $(this).parent().parent();
+
+ parent.children('li.open').children('a').children('.arrow').removeClass('open');
+ parent.children('li.open').children('.sub-menu').slideUp(200);
+ parent.children('li.open').removeClass('open');
+
+ var sub = jQuery(this).next();
+ if (sub.is(":visible")) {
+ jQuery('.arrow', jQuery(this)).removeClass("open");
+ jQuery(this).parent().removeClass("open");
+ sub.slideUp(200, function () {
+ handleSidebarAndContentHeight();
+ });
+ } else {
+ jQuery('.arrow', jQuery(this)).addClass("open");
+ jQuery(this).parent().addClass("open");
+ sub.slideDown(200, function () {
+ handleSidebarAndContentHeight();
+ });
+ }
+
+ e.preventDefault();
+ });
+
+ // handle ajax links
+ jQuery('.page-sidebar').on('click', ' li > a.ajaxify', function (e) {
+ e.preventDefault();
+ App.scrollTop();
+
+ var url = $(this).attr("href");
+ var menuContainer = jQuery('.page-sidebar ul');
+ var pageContent = $('.page-content');
+ var pageContentBody = $('.page-content .page-content-body');
+
+ menuContainer.children('li.active').removeClass('active');
+ menuContainer.children('arrow.open').removeClass('open');
+
+ $(this).parents('li').each(function () {
+ $(this).addClass('active');
+ $(this).children('a > span.arrow').addClass('open');
+ });
+ $(this).parents('li').addClass('active');
+
+ App.blockUI(pageContent, false);
+
+ $.post(url, {}, function (res) {
+ App.unblockUI(pageContent);
+ pageContentBody.html(res);
+ App.fixContentHeight(); // fix content height
+ App.initUniform(); // initialize uniform elements
+ });
+ });
+ }
+
+ var _calculateFixedSidebarViewportHeight = function () {
+ var sidebarHeight = $(window).height() - $('.header').height();
+ if ($('body').hasClass("page-footer-fixed")) {
+ sidebarHeight = sidebarHeight - $('.footer').height()-13;
+ }
+
+ return sidebarHeight;
+ }
+
+ var handleFixedSidebar = function () {
+ var menu = $('.page-sidebar-menu');
+
+ if (menu.parent('.slimScrollDiv').size() === 1) { // destroy existing instance before updating the height
+ menu.slimScroll({
+ destroy: true
+ });
+ menu.removeAttr('style');
+ $('.page-sidebar').removeAttr('style');
+ }
+
+ if ($('.page-sidebar-fixed').size() === 0) {
+ handleSidebarAndContentHeight();
+ return;
+ }
+
+ if ($(window).width() >= 980) {
+ var sidebarHeight = _calculateFixedSidebarViewportHeight();
+
+ menu.slimScroll({
+ size: '7px',
+ color: '#a1b2bd',
+ opacity: .3,
+ position: isRTL ? 'left' : ($('.page-sidebar-on-right').size() === 1 ? 'left' : 'right'),
+ height: sidebarHeight,
+ allowPageScroll: false,
+ disableFadeOut: false
+ });
+ handleSidebarAndContentHeight();
+ }
+ }
+
+ var handleFixedSidebarHoverable = function () {
+ if ($('body').hasClass('page-sidebar-fixed') === false) {
+ return;
+ }
+
+ $('.page-sidebar').off('mouseenter').on('mouseenter', function () {
+ var body = $('body');
+
+ if ((body.hasClass('page-sidebar-closed') === false || body.hasClass('page-sidebar-fixed') === false) || $(this).hasClass('page-sidebar-hovering')) {
+ return;
+ }
+
+ body.removeClass('page-sidebar-closed').addClass('page-sidebar-hover-on');
+ $(this).addClass('page-sidebar-hovering');
+ $(this).animate({
+ width: sidebarWidth
+ }, 400, '', function () {
+ $(this).removeClass('page-sidebar-hovering');
+ });
+ });
+
+ $('.page-sidebar').off('mouseleave').on('mouseleave', function () {
+ var body = $('body');
+
+ if ((body.hasClass('page-sidebar-hover-on') === false || body.hasClass('page-sidebar-fixed') === false) || $(this).hasClass('page-sidebar-hovering')) {
+ return;
+ }
+
+ $(this).addClass('page-sidebar-hovering');
+ $(this).animate({
+ width: sidebarCollapsedWidth
+ }, 400, '', function () {
+ $('body').addClass('page-sidebar-closed').removeClass('page-sidebar-hover-on');
+ $(this).removeClass('page-sidebar-hovering');
+ });
+ });
+ }
+
+ var handleSidebarToggler = function () {
+ // handle sidebar show/hide
+ $('.page-sidebar').on('click', '.sidebar-toggler', function (e) {
+ var body = $('body');
+ var sidebar = $('.page-sidebar');
+
+ if ((body.hasClass("page-sidebar-hover-on") && body.hasClass('page-sidebar-fixed')) || sidebar.hasClass('page-sidebar-hovering')) {
+ body.removeClass('page-sidebar-hover-on');
+ sidebar.css('width', '').hide().show();
+ e.stopPropagation();
+ runResponsiveHandlers();
+ return;
+ }
+
+ $(".sidebar-search", sidebar).removeClass("open");
+
+ if (body.hasClass("page-sidebar-closed")) {
+ body.removeClass("page-sidebar-closed");
+ if (body.hasClass('page-sidebar-fixed')) {
+ sidebar.css('width', '');
+ }
+ } else {
+ body.addClass("page-sidebar-closed");
+ }
+ runResponsiveHandlers();
+ });
+
+ // handle the search bar close
+ $('.page-sidebar').on('click', '.sidebar-search .remove', function (e) {
+ e.preventDefault();
+ $('.sidebar-search').removeClass("open");
+ });
+
+ // handle the search query submit on enter press
+ $('.page-sidebar').on('keypress', '.sidebar-search input', function (e) {
+ if (e.which == 13) {
+ window.location.href = "extra_search.html";
+ return false; //<---- Add this line
+ }
+ });
+
+ // handle the search submit
+ $('.sidebar-search .submit').on('click', function (e) {
+ e.preventDefault();
+
+ if ($('body').hasClass("page-sidebar-closed")) {
+ if ($('.sidebar-search').hasClass('open') == false) {
+ if ($('.page-sidebar-fixed').size() === 1) {
+ $('.page-sidebar .sidebar-toggler').click(); //trigger sidebar toggle button
+ }
+ $('.sidebar-search').addClass("open");
+ } else {
+ window.location.href = "extra_search.html";
+ }
+ } else {
+ window.location.href = "extra_search.html";
+ }
+ });
+ }
+
+ var handleHorizontalMenu = function () {
+ //handle hor menu search form toggler click
+ $('.header').on('click', '.hor-menu .hor-menu-search-form-toggler', function (e) {
+ if ($(this).hasClass('hide')) {
+ $(this).removeClass('hide');
+ $('.header .hor-menu .search-form').hide();
+ } else {
+ $(this).addClass('hide');
+ $('.header .hor-menu .search-form').show();
+ }
+ e.preventDefault();
+ });
+
+ //handle hor menu search button click
+ $('.header').on('click', '.hor-menu .search-form .btn', function (e) {
+ window.location.href = "extra_search.html";
+ e.preventDefault();
+ });
+
+ //handle hor menu search form on enter press
+ $('.header').on('keypress', '.hor-menu .search-form input', function (e) {
+ if (e.which == 13) {
+ window.location.href = "extra_search.html";
+ return false;
+ }
+ });
+ }
+
+ var handleGoTop = function () {
+ /* set variables locally for increased performance */
+ jQuery('.footer').on('click', '.go-top', function (e) {
+ App.scrollTo();
+ e.preventDefault();
+ });
+ }
+
+ var handlePortletTools = function () {
+ jQuery('body').on('click', '.portlet .tools a.remove', function (e) {
+ e.preventDefault();
+ var removable = jQuery(this).parents(".portlet");
+ if (removable.next().hasClass('portlet') || removable.prev().hasClass('portlet')) {
+ jQuery(this).parents(".portlet").remove();
+ } else {
+ jQuery(this).parents(".portlet").parent().remove();
+ }
+ });
+
+ jQuery('body').on('click', '.portlet .tools a.reload', function (e) {
+ e.preventDefault();
+ var el = jQuery(this).parents(".portlet");
+ App.blockUI(el);
+ window.setTimeout(function () {
+ App.unblockUI(el);
+ }, 1000);
+ });
+
+ jQuery('body').on('click', '.portlet .tools .collapse, .portlet .tools .expand', function (e) {
+ e.preventDefault();
+ var el = jQuery(this).closest(".portlet").children(".portlet-body");
+ if (jQuery(this).hasClass("collapse")) {
+ jQuery(this).removeClass("collapse").addClass("expand");
+ el.slideUp(200);
+ } else {
+ jQuery(this).removeClass("expand").addClass("collapse");
+ el.slideDown(200);
+ }
+ });
+ }
+
+ var handleUniform = function () {
+ if (!jQuery().uniform) {
+ return;
+ }
+ var test = $("input[type=checkbox]:not(.toggle), input[type=radio]:not(.toggle, .star)");
+ if (test.size() > 0) {
+ test.each(function () {
+ if ($(this).parents(".checker").size() == 0) {
+ $(this).show();
+ $(this).uniform();
+ }
+ });
+ }
+ }
+
+ var handleAccordions = function () {
+ $(".accordion").collapse().height('auto');
+
+ var lastClicked;
+
+ //add scrollable class name if you need scrollable panes
+ jQuery('body').on('click', '.accordion.scrollable .accordion-toggle', function () {
+ lastClicked = jQuery(this);
+ }); //move to faq section
+
+ jQuery('body').on('shown', '.accordion.scrollable', function () {
+ jQuery('html,body').animate({
+ scrollTop: lastClicked.offset().top - 150
+ }, 'slow');
+ });
+ }
+
+ var handleTabs = function () {
+
+ // function to fix left/right tab contents
+ var fixTabHeight = function(tab) {
+ $(tab).each(function() {
+ var content = $($($(this).attr("href")));
+ var tab = $(this).parent().parent();
+ if (tab.height() > content.height()) {
+ content.css('min-height', tab.height());
+ }
+ });
+ }
+
+ // fix tab content on tab shown
+ $('body').on('shown', '.nav.nav-tabs.tabs-left a[data-toggle="tab"], .nav.nav-tabs.tabs-right a[data-toggle="tab"]', function(){
+ fixTabHeight($(this));
+ });
+
+ $('body').on('shown', '.nav.nav-tabs', function(){
+ handleSidebarAndContentHeight();
+ });
+
+ //fix tab contents for left/right tabs
+ fixTabHeight('.nav.nav-tabs.tabs-left > li.active > a[data-toggle="tab"], .nav.nav-tabs.tabs-right > li.active > a[data-toggle="tab"]');
+
+ //activate tab if tab id provided in the URL
+ if(location.hash) {
+ var tabid = location.hash.substr(1);
+ $('a[href="#'+tabid+'"]').click();
+ }
+ }
+
+ var handleScrollers = function () {
+ $('.scroller').each(function () {
+ $(this).slimScroll({
+ size: '7px',
+ color: '#a1b2bd',
+ position: isRTL ? 'left' : 'right',
+ height: $(this).attr("data-height"),
+ alwaysVisible: ($(this).attr("data-always-visible") == "1" ? true : false),
+ railVisible: ($(this).attr("data-rail-visible") == "1" ? true : false),
+ disableFadeOut: true
+ });
+ });
+ }
+
+ var handleTooltips = function () {
+ if (App.isTouchDevice()) { // if touch device, some tooltips can be skipped in order to not conflict with click events
+ jQuery('.tooltips:not(.no-tooltip-on-touch-device)').tooltip();
+ } else {
+ jQuery('.tooltips').tooltip();
+ }
+ }
+
+ var handleDropdowns = function () {
+ $('body').on('click', '.dropdown-menu.hold-on-click', function(e){
+ e.stopPropagation();
+ })
+ }
+
+ var handlePopovers = function () {
+ jQuery('.popovers').popover();
+ }
+
+ var handleChoosenSelect = function () {
+ if (!jQuery().chosen) {
+ return;
+ }
+
+ $(".chosen").each(function () {
+ $(this).chosen({
+ allow_single_deselect: $(this).attr("data-with-diselect") === "1" ? true : false
+ });
+ });
+ }
+
+ var handleFancybox = function () {
+ if (!jQuery.fancybox) {
+ return;
+ }
+
+ if (jQuery(".fancybox-button").size() > 0) {
+ jQuery(".fancybox-button").fancybox({
+ groupAttr: 'data-rel',
+ prevEffect: 'none',
+ nextEffect: 'none',
+ closeBtn: true,
+ helpers: {
+ title: {
+ type: 'inside'
+ }
+ }
+ });
+ }
+ }
+
+ var handleTheme = function () {
+
+ var panel = $('.color-panel');
+
+ if ($('body').hasClass('page-boxed') == false) {
+ $('.layout-option', panel).val("fluid");
+ }
+
+ $('.sidebar-option', panel).val("default");
+ $('.header-option', panel).val("fixed");
+ $('.footer-option', panel).val("default");
+
+ //handle theme layout
+ var resetLayout = function () {
+ $("body").
+ removeClass("page-boxed").
+ removeClass("page-footer-fixed").
+ removeClass("page-sidebar-fixed").
+ removeClass("page-header-fixed");
+
+ $('.header > .navbar-inner > .container').removeClass("container").addClass("container-fluid");
+
+ if ($('.page-container').parent(".container").size() === 1) {
+ $('.page-container').insertAfter('.header');
+ }
+
+ if ($('.footer > .container').size() === 1) {
+ $('.footer').html($('.footer > .container').html());
+ } else if ($('.footer').parent(".container").size() === 1) {
+ $('.footer').insertAfter('.page-container');
+ }
+
+ $('body > .container').remove();
+ }
+
+ var lastSelectedLayout = '';
+
+ var setLayout = function () {
+
+ var layoutOption = $('.layout-option', panel).val();
+ var sidebarOption = $('.sidebar-option', panel).val();
+ var headerOption = $('.header-option', panel).val();
+ var footerOption = $('.footer-option', panel).val();
+
+ if (sidebarOption == "fixed" && headerOption == "default") {
+ alert('Default Header with Fixed Sidebar option is not supported. Proceed with Default Header with Default Sidebar.');
+ $('.sidebar-option', panel).val("default");
+ sidebarOption = 'default';
+ }
+
+ resetLayout(); // reset layout to default state
+
+ if (layoutOption === "boxed") {
+ $("body").addClass("page-boxed");
+
+ // set header
+ $('.header > .navbar-inner > .container-fluid').removeClass("container-fluid").addClass("container");
+ var cont = $('.header').after('');
+
+ // set content
+ $('.page-container').appendTo('body > .container');
+
+ // set footer
+ if (footerOption === 'fixed' || sidebarOption === 'default') {
+ $('.footer').html('
'+$('.footer').html()+'
');
+ } else {
+ $('.footer').appendTo('body > .container');
+ }
+ }
+
+ if (lastSelectedLayout != layoutOption) {
+ //layout changed, run responsive handler:
+ runResponsiveHandlers();
+ }
+ lastSelectedLayout = layoutOption;
+
+ //header
+ if (headerOption === 'fixed') {
+ $("body").addClass("page-header-fixed");
+ $(".header").removeClass("navbar-static-top").addClass("navbar-fixed-top");
+ } else {
+ $("body").removeClass("page-header-fixed");
+ $(".header").removeClass("navbar-fixed-top").addClass("navbar-static-top");
+ }
+
+ //sidebar
+ if (sidebarOption === 'fixed') {
+ $("body").addClass("page-sidebar-fixed");
+ } else {
+ $("body").removeClass("page-sidebar-fixed");
+ }
+
+ //footer
+ if (footerOption === 'fixed') {
+ $("body").addClass("page-footer-fixed");
+ } else {
+ $("body").removeClass("page-footer-fixed");
+ }
+
+ handleSidebarAndContentHeight(); // fix content height
+ handleFixedSidebar(); // reinitialize fixed sidebar
+ handleFixedSidebarHoverable(); // reinitialize fixed sidebar hover effect
+ }
+
+ // handle theme colors
+ var setColor = function (color) {
+ $('#style_color').attr("href", "assets/css/themes/" + color + ".css");
+ $.cookie('style_color', color);
+ }
+
+ $('.icon-color', panel).click(function () {
+ $('.color-mode').show();
+ $('.icon-color-close').show();
+ });
+
+ $('.icon-color-close', panel).click(function () {
+ $('.color-mode').hide();
+ $('.icon-color-close').hide();
+ });
+
+ $('li', panel).click(function () {
+ var color = $(this).attr("data-style");
+ setColor(color);
+ $('.inline li', panel).removeClass("current");
+ $(this).addClass("current");
+ });
+
+ $('.layout-option, .header-option, .sidebar-option, .footer-option', panel).change(setLayout);
+ }
+
+ var handleFixInputPlaceholderForIE = function () {
+ //fix html5 placeholder attribute for ie7 & ie8
+ if (isIE8 || isIE9) { // ie7&ie8
+ // this is html5 placeholder fix for inputs, inputs with placeholder-no-fix class will be skipped(e.g: we need this for password fields)
+ jQuery('input[placeholder]:not(.placeholder-no-fix), textarea[placeholder]:not(.placeholder-no-fix)').each(function () {
+
+ var input = jQuery(this);
+
+ if(input.val()=='' && input.attr("placeholder") != '') {
+ input.addClass("placeholder").val(input.attr('placeholder'));
+ }
+
+ input.focus(function () {
+ if (input.val() == input.attr('placeholder')) {
+ input.val('');
+ }
+ });
+
+ input.blur(function () {
+ if (input.val() == '' || input.val() == input.attr('placeholder')) {
+ input.val(input.attr('placeholder'));
+ }
+ });
+ });
+ }
+ }
+
+ //* END:CORE HANDLERS *//
+
+ return {
+
+ //main function to initiate template pages
+ init: function () {
+
+ //IMPORTANT!!!: Do not modify the core handlers call order.
+
+ //core handlers
+ handleInit();
+ handleResponsiveOnResize(); // set and handle responsive
+ handleUniform();
+ handleScrollers(); // handles slim scrolling contents
+ handleResponsiveOnInit(); // handler responsive elements on page load
+
+ //layout handlers
+ handleFixedSidebar(); // handles fixed sidebar menu
+ handleFixedSidebarHoverable(); // handles fixed sidebar on hover effect
+ handleSidebarMenu(); // handles main menu
+ handleHorizontalMenu(); // handles horizontal menu
+ handleSidebarToggler(); // handles sidebar hide/show
+ handleFixInputPlaceholderForIE(); // fixes/enables html5 placeholder attribute for IE9, IE8
+ handleGoTop(); //handles scroll to top functionality in the footer
+ handleTheme(); // handles style customer tool
+
+ //ui component handlers
+ handlePortletTools(); // handles portlet action bar functionality(refresh, configure, toggle, remove)
+ handleDropdowns(); // handle dropdowns
+ handleTabs(); // handle tabs
+ handleTooltips(); // handle bootstrap tooltips
+ handlePopovers(); // handles bootstrap popovers
+ handleAccordions(); //handles accordions
+ handleChoosenSelect(); // handles bootstrap chosen dropdowns
+
+ App.addResponsiveHandler(handleChoosenSelect); // reinitiate chosen dropdown on main content resize. disable this line if you don't really use chosen dropdowns.
+ },
+
+ fixContentHeight: function () {
+ handleSidebarAndContentHeight();
+ },
+
+ addResponsiveHandler: function (func) {
+ responsiveHandlers.push(func);
+ },
+
+ // useful function to make equal height for contacts stand side by side
+ setEqualHeight: function (els) {
+ var tallestEl = 0;
+ els = jQuery(els);
+ els.each(function () {
+ var currentHeight = $(this).height();
+ if (currentHeight > tallestEl) {
+ tallestColumn = currentHeight;
+ }
+ });
+ els.height(tallestEl);
+ },
+
+ // wrapper function to scroll to an element
+ scrollTo: function (el, offeset) {
+ pos = el ? el.offset().top : 0;
+ jQuery('html,body').animate({
+ scrollTop: pos + (offeset ? offeset : 0)
+ }, 'slow');
+ },
+
+ scrollTop: function () {
+ App.scrollTo();
+ },
+
+ // wrapper function to block element(indicate loading)
+ blockUI: function (el, centerY) {
+ var el = jQuery(el);
+ el.block({
+ message: '',
+ centerY: centerY != undefined ? centerY : true,
+ css: {
+ top: '10%',
+ border: 'none',
+ padding: '2px',
+ backgroundColor: 'none'
+ },
+ overlayCSS: {
+ backgroundColor: '#000',
+ opacity: 0.05,
+ cursor: 'wait'
+ }
+ });
+ },
+
+ // wrapper function to un-block element(finish loading)
+ unblockUI: function (el) {
+ jQuery(el).unblock({
+ onUnblock: function () {
+ jQuery(el).removeAttr("style");
+ }
+ });
+ },
+
+ // initializes uniform elements
+ initUniform: function (els) {
+
+ if (els) {
+ jQuery(els).each(function () {
+ if ($(this).parents(".checker").size() == 0) {
+ $(this).show();
+ $(this).uniform();
+ }
+ });
+ } else {
+ handleUniform();
+ }
+
+ },
+
+ // initializes choosen dropdowns
+ initChosenSelect: function (els) {
+ $(els).chosen({
+ allow_single_deselect: true
+ });
+ },
+
+ initFancybox: function () {
+ handleFancybox();
+ },
+
+ getActualVal: function (el) {
+ var el = jQuery(el);
+ if (el.val() === el.attr("placeholder")) {
+ return "";
+ }
+
+ return el.val();
+ },
+
+ getURLParameter: function (paramName) {
+ var searchString = window.location.search.substring(1),
+ i, val, params = searchString.split("&");
+
+ for (i = 0; i < params.length; i++) {
+ val = params[i].split("=");
+ if (val[0] == paramName) {
+ return unescape(val[1]);
+ }
+ }
+ return null;
+ },
+
+ // check for device touch support
+ isTouchDevice: function () {
+ try {
+ document.createEvent("TouchEvent");
+ return true;
+ } catch (e) {
+ return false;
+ }
+ },
+
+ isIE8: function () {
+ return isIE8;
+ },
+
+ isRTL: function () {
+ return isRTL;
+ },
+
+ getLayoutColorCode: function (name) {
+ if (layoutColorCodes[name]) {
+ return layoutColorCodes[name];
+ } else {
+ return '';
+ }
+ }
+
+ };
+
+}();
+
+
+$.fn.serializeJson=function(){
+ var serializeObj={};
+ var array=this.serializeArray();
+ var str=this.serialize();
+ $(array).each(function(){
+ if(serializeObj[this.name]){
+ if($.isArray(serializeObj[this.name])){
+ serializeObj[this.name].push(this.value);
+ }else{
+ serializeObj[this.name]=[serializeObj[this.name],this.value];
+ }
+ }else{
+ serializeObj[this.name]=this.value;
+ }
+ });
+ return serializeObj;
+};
\ No newline at end of file
diff --git a/mall-master/src/main/resources/static/js/bootstrap-colorpicker.js b/mall-master/src/main/resources/static/js/bootstrap-colorpicker.js
new file mode 100644
index 0000000..6a0fc8a
--- /dev/null
+++ b/mall-master/src/main/resources/static/js/bootstrap-colorpicker.js
@@ -0,0 +1,540 @@
+/* =========================================================
+ * bootstrap-colorpicker.js
+ * http://www.eyecon.ro/bootstrap-colorpicker
+ * =========================================================
+ * Copyright 2012 Stefan Petre
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+!function( $ ) {
+
+ // Color object
+
+ var Color = function(val) {
+ this.value = {
+ h: 1,
+ s: 1,
+ b: 1,
+ a: 1
+ };
+ this.setColor(val);
+ };
+
+ Color.prototype = {
+ constructor: Color,
+
+ //parse a string to HSB
+ setColor: function(val){
+ val = val.toLowerCase();
+ var that = this;
+ $.each( CPGlobal.stringParsers, function( i, parser ) {
+ var match = parser.re.exec( val ),
+ values = match && parser.parse( match ),
+ space = parser.space||'rgba';
+ if ( values ) {
+ if (space === 'hsla') {
+ that.value = CPGlobal.RGBtoHSB.apply(null, CPGlobal.HSLtoRGB.apply(null, values));
+ } else {
+ that.value = CPGlobal.RGBtoHSB.apply(null, values);
+ }
+ return false;
+ }
+ });
+ },
+
+ setHue: function(h) {
+ this.value.h = 1- h;
+ },
+
+ setSaturation: function(s) {
+ this.value.s = s;
+ },
+
+ setLightness: function(b) {
+ this.value.b = 1- b;
+ },
+
+ setAlpha: function(a) {
+ this.value.a = parseInt((1 - a)*100, 10)/100;
+ },
+
+ // HSBtoRGB from RaphaelJS
+ // https://github.com/DmitryBaranovskiy/raphael/
+ toRGB: function(h, s, b, a) {
+ if (!h) {
+ h = this.value.h;
+ s = this.value.s;
+ b = this.value.b;
+ }
+ h *= 360;
+ var R, G, B, X, C;
+ h = (h % 360) / 60;
+ C = b * s;
+ X = C * (1 - Math.abs(h % 2 - 1));
+ R = G = B = b - C;
+
+ h = ~~h;
+ R += [C, X, 0, 0, X, C][h];
+ G += [X, C, C, X, 0, 0][h];
+ B += [0, 0, X, C, C, X][h];
+ return {
+ r: Math.round(R*255),
+ g: Math.round(G*255),
+ b: Math.round(B*255),
+ a: a||this.value.a
+ };
+ },
+
+ toHex: function(h, s, b, a){
+ var rgb = this.toRGB(h, s, b, a);
+ return '#'+((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1);
+ },
+
+ toHSL: function(h, s, b, a){
+ if (!h) {
+ h = this.value.h;
+ s = this.value.s;
+ b = this.value.b;
+ }
+ var H = h,
+ L = (2 - s) * b,
+ S = s * b;
+ if (L > 0 && L <= 1) {
+ S /= L;
+ } else {
+ S /= 2 - L;
+ }
+ L /= 2;
+ if (S > 1) {
+ S = 1;
+ }
+ return {
+ h: H,
+ s: S,
+ l: L,
+ a: a||this.value.a
+ };
+ }
+ };
+
+ // Picker object
+
+ var Colorpicker = function(element, options){
+ this.element = $(element);
+ var format = options.format||this.element.data('color-format')||'hex';
+ this.format = CPGlobal.translateFormats[format];
+ this.isInput = this.element.is('input');
+ this.component = this.element.is('.color') ? this.element.find('.add-on') : false;
+
+ this.picker = $(CPGlobal.template)
+ .appendTo('body')
+ .on('mousedown', $.proxy(this.mousedown, this));
+
+ if (this.isInput) {
+ this.element.on({
+ 'focus': $.proxy(this.show, this),
+ 'keyup': $.proxy(this.update, this)
+ });
+ } else if (this.component){
+ this.component.on({
+ 'click': $.proxy(this.show, this)
+ });
+ } else {
+ this.element.on({
+ 'click': $.proxy(this.show, this)
+ });
+ }
+ if (format === 'rgba' || format === 'hsla') {
+ this.picker.addClass('alpha');
+ this.alpha = this.picker.find('.colorpicker-alpha')[0].style;
+ }
+
+ if (this.component){
+ this.picker.find('.colorpicker-color').hide();
+ this.preview = this.element.find('i')[0].style;
+ } else {
+ this.preview = this.picker.find('div:last')[0].style;
+ }
+
+ this.base = this.picker.find('div:first')[0].style;
+ this.update();
+ };
+
+ Colorpicker.prototype = {
+ constructor: Colorpicker,
+
+ show: function(e) {
+ this.picker.show();
+ this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
+ this.place();
+ $(window).on('resize', $.proxy(this.place, this));
+ if (!this.isInput) {
+ if (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+ $(document).on({
+ 'mousedown': $.proxy(this.hide, this)
+ });
+ this.element.trigger({
+ type: 'show',
+ color: this.color
+ });
+ },
+
+ update: function(){
+ this.color = new Color(this.isInput ? this.element.prop('value') : this.element.data('color'));
+ this.picker.find('i')
+ .eq(0).css({left: this.color.value.s*100, top: 100 - this.color.value.b*100}).end()
+ .eq(1).css('top', 100 * (1 - this.color.value.h)).end()
+ .eq(2).css('top', 100 * (1 - this.color.value.a));
+ this.previewColor();
+ },
+
+ setValue: function(newColor) {
+ this.color = new Color(newColor);
+ this.picker.find('i')
+ .eq(0).css({left: this.color.value.s*100, top: 100 - this.color.value.b*100}).end()
+ .eq(1).css('top', 100 * (1 - this.color.value.h)).end()
+ .eq(2).css('top', 100 * (1 - this.color.value.a));
+ this.previewColor();
+ this.element.trigger({
+ type: 'changeColor',
+ color: this.color
+ });
+ },
+
+ hide: function(){
+ this.picker.hide();
+ $(window).off('resize', this.place);
+ if (!this.isInput) {
+ $(document).off({
+ 'mousedown': this.hide
+ });
+ if (this.component){
+ this.element.find('input').prop('value', this.format.call(this));
+ }
+ this.element.data('color', this.format.call(this));
+ } else {
+ this.element.prop('value', this.format.call(this));
+ }
+ this.element.trigger({
+ type: 'hide',
+ color: this.color
+ });
+ },
+
+ place: function(){
+ var offset = this.component ? this.component.offset() : this.element.offset();
+ this.picker.css({
+ top: offset.top + this.height,
+ left: offset.left
+ });
+ },
+
+ //preview color change
+ previewColor: function(){
+ try {
+ this.preview.backgroundColor = this.format.call(this);
+ } catch(e) {
+ this.preview.backgroundColor = this.color.toHex();
+ }
+ //set the color for brightness/saturation slider
+ this.base.backgroundColor = this.color.toHex(this.color.value.h, 1, 1, 1);
+ //set te color for alpha slider
+ if (this.alpha) {
+ this.alpha.backgroundColor = this.color.toHex();
+ }
+ },
+
+ pointer: null,
+
+ slider: null,
+
+ mousedown: function(e){
+ e.stopPropagation();
+ e.preventDefault();
+
+ var target = $(e.target);
+
+ //detect the slider and set the limits and callbacks
+ var zone = target.closest('div');
+ if (!zone.is('.colorpicker')) {
+ if (zone.is('.colorpicker-saturation')) {
+ this.slider = $.extend({}, CPGlobal.sliders.saturation);
+ }
+ else if (zone.is('.colorpicker-hue')) {
+ this.slider = $.extend({}, CPGlobal.sliders.hue);
+ }
+ else if (zone.is('.colorpicker-alpha')) {
+ this.slider = $.extend({}, CPGlobal.sliders.alpha);
+ } else {
+ return false;
+ }
+ var offset = zone.offset();
+ //reference to knob's style
+ this.slider.knob = zone.find('i')[0].style;
+ this.slider.left = e.pageX - offset.left;
+ this.slider.top = e.pageY - offset.top;
+ this.pointer = {
+ left: e.pageX,
+ top: e.pageY
+ };
+ //trigger mousemove to move the knob to the current position
+ $(document).on({
+ mousemove: $.proxy(this.mousemove, this),
+ mouseup: $.proxy(this.mouseup, this)
+ }).trigger('mousemove');
+ }
+ return false;
+ },
+
+ mousemove: function(e){
+ e.stopPropagation();
+ e.preventDefault();
+ var left = Math.max(
+ 0,
+ Math.min(
+ this.slider.maxLeft,
+ this.slider.left + ((e.pageX||this.pointer.left) - this.pointer.left)
+ )
+ );
+ var top = Math.max(
+ 0,
+ Math.min(
+ this.slider.maxTop,
+ this.slider.top + ((e.pageY||this.pointer.top) - this.pointer.top)
+ )
+ );
+ this.slider.knob.left = left + 'px';
+ this.slider.knob.top = top + 'px';
+ if (this.slider.callLeft) {
+ this.color[this.slider.callLeft].call(this.color, left/100);
+ }
+ if (this.slider.callTop) {
+ this.color[this.slider.callTop].call(this.color, top/100);
+ }
+ this.previewColor();
+ this.element.trigger({
+ type: 'changeColor',
+ color: this.color
+ });
+ return false;
+ },
+
+ mouseup: function(e){
+ e.stopPropagation();
+ e.preventDefault();
+ $(document).off({
+ mousemove: this.mousemove,
+ mouseup: this.mouseup
+ });
+ return false;
+ }
+ }
+
+ $.fn.colorpicker = function ( option ) {
+ return this.each(function () {
+ var $this = $(this),
+ data = $this.data('colorpicker'),
+ options = typeof option === 'object' && option;
+ if (!data) {
+ $this.data('colorpicker', (data = new Colorpicker(this, $.extend({}, $.fn.colorpicker.defaults,options))));
+ }
+ if (typeof option === 'string') data[option]();
+ });
+ };
+
+ $.fn.colorpicker.defaults = {
+ };
+
+ $.fn.colorpicker.Constructor = Colorpicker;
+
+ var CPGlobal = {
+
+ // translate a format from Color object to a string
+ translateFormats: {
+ 'rgb': function(){
+ var rgb = this.color.toRGB();
+ return 'rgb('+rgb.r+','+rgb.g+','+rgb.b+')';
+ },
+
+ 'rgba': function(){
+ var rgb = this.color.toRGB();
+ return 'rgba('+rgb.r+','+rgb.g+','+rgb.b+','+rgb.a+')';
+ },
+
+ 'hsl': function(){
+ var hsl = this.color.toHSL();
+ return 'hsl('+Math.round(hsl.h*360)+','+Math.round(hsl.s*100)+'%,'+Math.round(hsl.l*100)+'%)';
+ },
+
+ 'hsla': function(){
+ var hsl = this.color.toHSL();
+ return 'hsla('+Math.round(hsl.h*360)+','+Math.round(hsl.s*100)+'%,'+Math.round(hsl.l*100)+'%,'+hsl.a+')';
+ },
+
+ 'hex': function(){
+ return this.color.toHex();
+ }
+ },
+
+ sliders: {
+ saturation: {
+ maxLeft: 100,
+ maxTop: 100,
+ callLeft: 'setSaturation',
+ callTop: 'setLightness'
+ },
+
+ hue: {
+ maxLeft: 0,
+ maxTop: 100,
+ callLeft: false,
+ callTop: 'setHue'
+ },
+
+ alpha: {
+ maxLeft: 0,
+ maxTop: 100,
+ callLeft: false,
+ callTop: 'setAlpha'
+ }
+ },
+
+ // HSBtoRGB from RaphaelJS
+ // https://github.com/DmitryBaranovskiy/raphael/
+ RGBtoHSB: function (r, g, b, a){
+ r /= 255;
+ g /= 255;
+ b /= 255;
+
+ var H, S, V, C;
+ V = Math.max(r, g, b);
+ C = V - Math.min(r, g, b);
+ H = (C === 0 ? null :
+ V == r ? (g - b) / C :
+ V == g ? (b - r) / C + 2 :
+ (r - g) / C + 4
+ );
+ H = ((H + 360) % 6) * 60 / 360;
+ S = C === 0 ? 0 : C / V;
+ return {h: H||1, s: S, b: V, a: a||1};
+ },
+
+ HueToRGB: function (p, q, h) {
+ if (h < 0)
+ h += 1;
+ else if (h > 1)
+ h -= 1;
+
+ if ((h * 6) < 1)
+ return p + (q - p) * h * 6;
+ else if ((h * 2) < 1)
+ return q;
+ else if ((h * 3) < 2)
+ return p + (q - p) * ((2 / 3) - h) * 6;
+ else
+ return p;
+ },
+
+ HSLtoRGB: function (h, s, l, a)
+ {
+ if (s < 0) {
+ s = 0;
+ }
+ var q;
+ if (l <= 0.5) {
+ q = l * (1 + s);
+ } else {
+ q = l + s - (l * s);
+ }
+
+ var p = 2 * l - q;
+
+ var tr = h + (1 / 3);
+ var tg = h;
+ var tb = h - (1 / 3);
+
+ var r = Math.round(CPGlobal.HueToRGB(p, q, tr) * 255);
+ var g = Math.round(CPGlobal.HueToRGB(p, q, tg) * 255);
+ var b = Math.round(CPGlobal.HueToRGB(p, q, tb) * 255);
+ return [r, g, b, a||1];
+ },
+
+ // a set of RE's that can match strings and generate color tuples.
+ // from John Resig color plugin
+ // https://github.com/jquery/jquery-color/
+ stringParsers: [
+ {
+ re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
+ parse: function( execResult ) {
+ return [
+ execResult[ 1 ],
+ execResult[ 2 ],
+ execResult[ 3 ],
+ execResult[ 4 ]
+ ];
+ }
+ }, {
+ re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
+ parse: function( execResult ) {
+ return [
+ 2.55 * execResult[1],
+ 2.55 * execResult[2],
+ 2.55 * execResult[3],
+ execResult[ 4 ]
+ ];
+ }
+ }, {
+ re: /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
+ parse: function( execResult ) {
+ return [
+ parseInt( execResult[ 1 ], 16 ),
+ parseInt( execResult[ 2 ], 16 ),
+ parseInt( execResult[ 3 ], 16 )
+ ];
+ }
+ }, {
+ re: /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
+ parse: function( execResult ) {
+ return [
+ parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
+ parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
+ parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
+ ];
+ }
+ }, {
+ re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
+ space: 'hsla',
+ parse: function( execResult ) {
+ return [
+ execResult[1]/360,
+ execResult[2] / 100,
+ execResult[3] / 100,
+ execResult[4]
+ ];
+ }
+ }
+ ],
+ template: '
'+
+ '
'+
+ '
'+
+ '
'+
+ '
'+
+ '
'
+ };
+
+}( window.jQuery )
\ No newline at end of file
diff --git a/mall-master/src/main/resources/static/js/bootstrap-datepicker.js b/mall-master/src/main/resources/static/js/bootstrap-datepicker.js
new file mode 100644
index 0000000..8a1abf9
--- /dev/null
+++ b/mall-master/src/main/resources/static/js/bootstrap-datepicker.js
@@ -0,0 +1,1248 @@
+/* =========================================================
+ * bootstrap-datepicker.js
+ * http://www.eyecon.ro/bootstrap-datepicker
+ * =========================================================
+ * Copyright 2012 Stefan Petre
+ * Improvements by Andrew Rowls
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+!function( $ ) {
+
+ function UTCDate(){
+ return new Date(Date.UTC.apply(Date, arguments));
+ }
+ function UTCToday(){
+ var today = new Date();
+ return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
+ }
+
+ // Picker object
+
+ var Datepicker = function(element, options) {
+ var that = this;
+
+ this._process_options(options);
+
+ this.element = $(element);
+ this.isInline = false;
+ this.isInput = this.element.is('input');
+ this.component = this.element.is('.date') ? this.element.find('.add-on, .btn') : false;
+ this.hasInput = this.component && this.element.find('input').length;
+ if(this.component && this.component.length === 0)
+ this.component = false;
+
+ this.picker = $(DPGlobal.template);
+ this._buildEvents();
+ this._attachEvents();
+
+ if(this.isInline) {
+ this.picker.addClass('datepicker-inline').appendTo(this.element);
+ } else {
+ this.picker.addClass('datepicker-dropdown dropdown-menu');
+ }
+
+ if (this.o.rtl){
+ this.picker.addClass('datepicker-rtl');
+ this.picker.find('.prev i, .next i')
+ .toggleClass('icon-arrow-left icon-arrow-right');
+ }
+
+
+ this.viewMode = this.o.startView;
+
+ if (this.o.calendarWeeks)
+ this.picker.find('tfoot th.today')
+ .attr('colspan', function(i, val){
+ return parseInt(val) + 1;
+ });
+
+ this._allow_update = false;
+
+ this.setStartDate(this.o.startDate);
+ this.setEndDate(this.o.endDate);
+ this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);
+
+ this.fillDow();
+ this.fillMonths();
+
+ this._allow_update = true;
+
+ this.update();
+ this.showMode();
+
+ if(this.isInline) {
+ this.show();
+ }
+ };
+
+ Datepicker.prototype = {
+ constructor: Datepicker,
+
+ _process_options: function(opts){
+ // Store raw options for reference
+ this._o = $.extend({}, this._o, opts);
+ // Processed options
+ var o = this.o = $.extend({}, this._o);
+
+ // Check if "de-DE" style date is available, if not language should
+ // fallback to 2 letter code eg "de"
+ var lang = o.language;
+ if (!dates[lang]) {
+ lang = lang.split('-')[0];
+ if (!dates[lang])
+ lang = $.fn.datepicker.defaults.language;
+ }
+ o.language = lang;
+
+ switch(o.startView){
+ case 2:
+ case 'decade':
+ o.startView = 2;
+ break;
+ case 1:
+ case 'year':
+ o.startView = 1;
+ break;
+ default:
+ o.startView = 0;
+ }
+
+ switch (o.minViewMode) {
+ case 1:
+ case 'months':
+ o.minViewMode = 1;
+ break;
+ case 2:
+ case 'years':
+ o.minViewMode = 2;
+ break;
+ default:
+ o.minViewMode = 0;
+ }
+
+ o.startView = Math.max(o.startView, o.minViewMode);
+
+ o.weekStart %= 7;
+ o.weekEnd = ((o.weekStart + 6) % 7);
+
+ var format = DPGlobal.parseFormat(o.format)
+ if (o.startDate !== -Infinity) {
+ o.startDate = DPGlobal.parseDate(o.startDate, format, o.language);
+ }
+ if (o.endDate !== Infinity) {
+ o.endDate = DPGlobal.parseDate(o.endDate, format, o.language);
+ }
+
+ o.daysOfWeekDisabled = o.daysOfWeekDisabled||[];
+ if (!$.isArray(o.daysOfWeekDisabled))
+ o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/);
+ o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function (d) {
+ return parseInt(d, 10);
+ });
+ },
+ _events: [],
+ _secondaryEvents: [],
+ _applyEvents: function(evs){
+ for (var i=0, el, ev; i this.o.endDate) {
+ this.viewDate = new Date(this.o.endDate);
+ } else {
+ this.viewDate = new Date(this.date);
+ }
+ this.fill();
+ },
+
+ fillDow: function(){
+ var dowCnt = this.o.weekStart,
+ html = '
';
+ if(this.o.calendarWeeks){
+ var cell = '
';
+ html += cell;
+ this.picker.find('.datepicker-days thead tr:first-child').prepend(cell);
+ }
+ while (dowCnt < this.o.weekStart + 7) {
+ html += '
'+dates[this.o.language].daysMin[(dowCnt++)%7]+'
';
+ }
+ html += '
';
+ this.picker.find('.datepicker-days thead').append(html);
+ },
+
+ fillMonths: function(){
+ var html = '',
+ i = 0;
+ while (i < 12) {
+ html += ''+dates[this.o.language].monthsShort[i++]+'';
+ }
+ this.picker.find('.datepicker-months td').html(html);
+ },
+
+ setRange: function(range){
+ if (!range || !range.length)
+ delete this.range;
+ else
+ this.range = $.map(range, function(d){ return d.valueOf(); });
+ this.fill();
+ },
+
+ getClassNames: function(date){
+ var cls = [],
+ year = this.viewDate.getUTCFullYear(),
+ month = this.viewDate.getUTCMonth(),
+ currentDate = this.date.valueOf(),
+ today = new Date();
+ if (date.getUTCFullYear() < year || (date.getUTCFullYear() == year && date.getUTCMonth() < month)) {
+ cls.push('old');
+ } else if (date.getUTCFullYear() > year || (date.getUTCFullYear() == year && date.getUTCMonth() > month)) {
+ cls.push('new');
+ }
+ // Compare internal UTC date with local today, not UTC today
+ if (this.o.todayHighlight &&
+ date.getUTCFullYear() == today.getFullYear() &&
+ date.getUTCMonth() == today.getMonth() &&
+ date.getUTCDate() == today.getDate()) {
+ cls.push('today');
+ }
+ if (currentDate && date.valueOf() == currentDate) {
+ cls.push('active');
+ }
+ if (date.valueOf() < this.o.startDate || date.valueOf() > this.o.endDate ||
+ $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1) {
+ cls.push('disabled');
+ }
+ if (this.range){
+ if (date > this.range[0] && date < this.range[this.range.length-1]){
+ cls.push('range');
+ }
+ if ($.inArray(date.valueOf(), this.range) != -1){
+ cls.push('selected');
+ }
+ }
+ return cls;
+ },
+
+ fill: function() {
+ var d = new Date(this.viewDate),
+ year = d.getUTCFullYear(),
+ month = d.getUTCMonth(),
+ startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
+ startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
+ endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
+ endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
+ currentDate = this.date && this.date.valueOf(),
+ tooltip;
+ this.picker.find('.datepicker-days thead th.datepicker-switch')
+ .text(dates[this.o.language].months[month]+' '+year);
+ this.picker.find('tfoot th.today')
+ .text(dates[this.o.language].today)
+ .toggle(this.o.todayBtn !== false);
+ this.picker.find('tfoot th.clear')
+ .text(dates[this.o.language].clear)
+ .toggle(this.o.clearBtn !== false);
+ this.updateNavArrows();
+ this.fillMonths();
+ var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
+ day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
+ prevMonth.setUTCDate(day);
+ prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
+ var nextMonth = new Date(prevMonth);
+ nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
+ nextMonth = nextMonth.valueOf();
+ var html = [];
+ var clsName;
+ while(prevMonth.valueOf() < nextMonth) {
+ if (prevMonth.getUTCDay() == this.o.weekStart) {
+ html.push('
');
+ if(this.o.calendarWeeks){
+ // ISO 8601: First week contains first thursday.
+ // ISO also states week starts on Monday, but we can be more abstract here.
+ var
+ // Start of current week: based on weekstart/current date
+ ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
+ // Thursday of this week
+ th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
+ // First Thursday of year, year from thursday
+ yth = new Date(+(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
+ // Calendar week: ms between thursdays, div ms per day, div 7 days
+ calWeek = (th - yth) / 864e5 / 7 + 1;
+ html.push('
'+ calWeek +'
');
+
+ }
+ }
+ clsName = this.getClassNames(prevMonth);
+ clsName.push('day');
+
+ var before = this.o.beforeShowDay(prevMonth);
+ if (before === undefined)
+ before = {};
+ else if (typeof(before) === 'boolean')
+ before = {enabled: before};
+ else if (typeof(before) === 'string')
+ before = {classes: before};
+ if (before.enabled === false)
+ clsName.push('disabled');
+ if (before.classes)
+ clsName = clsName.concat(before.classes.split(/\s+/));
+ if (before.tooltip)
+ tooltip = before.tooltip;
+
+ clsName = $.unique(clsName);
+ html.push('
'+prevMonth.getUTCDate() + '
');
+ if (prevMonth.getUTCDay() == this.o.weekEnd) {
+ html.push('
');
+ }
+ prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
+ }
+ this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
+ var currentYear = this.date && this.date.getUTCFullYear();
+
+ var months = this.picker.find('.datepicker-months')
+ .find('th:eq(1)')
+ .text(year)
+ .end()
+ .find('span').removeClass('active');
+ if (currentYear && currentYear == year) {
+ months.eq(this.date.getUTCMonth()).addClass('active');
+ }
+ if (year < startYear || year > endYear) {
+ months.addClass('disabled');
+ }
+ if (year == startYear) {
+ months.slice(0, startMonth).addClass('disabled');
+ }
+ if (year == endYear) {
+ months.slice(endMonth+1).addClass('disabled');
+ }
+
+ html = '';
+ year = parseInt(year/10, 10) * 10;
+ var yearCont = this.picker.find('.datepicker-years')
+ .find('th:eq(1)')
+ .text(year + '-' + (year + 9))
+ .end()
+ .find('td');
+ year -= 1;
+ for (var i = -1; i < 11; i++) {
+ html += ''+year+'';
+ year += 1;
+ }
+ yearCont.html(html);
+ },
+
+ updateNavArrows: function() {
+ if (!this._allow_update) return;
+
+ var d = new Date(this.viewDate),
+ year = d.getUTCFullYear(),
+ month = d.getUTCMonth();
+ switch (this.viewMode) {
+ case 0:
+ if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()) {
+ this.picker.find('.prev').css({visibility: 'hidden'});
+ } else {
+ this.picker.find('.prev').css({visibility: 'visible'});
+ }
+ if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()) {
+ this.picker.find('.next').css({visibility: 'hidden'});
+ } else {
+ this.picker.find('.next').css({visibility: 'visible'});
+ }
+ break;
+ case 1:
+ case 2:
+ if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear()) {
+ this.picker.find('.prev').css({visibility: 'hidden'});
+ } else {
+ this.picker.find('.prev').css({visibility: 'visible'});
+ }
+ if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear()) {
+ this.picker.find('.next').css({visibility: 'hidden'});
+ } else {
+ this.picker.find('.next').css({visibility: 'visible'});
+ }
+ break;
+ }
+ },
+
+ click: function(e) {
+ e.preventDefault();
+ var target = $(e.target).closest('span, td, th');
+ if (target.length == 1) {
+ switch(target[0].nodeName.toLowerCase()) {
+ case 'th':
+ switch(target[0].className) {
+ case 'datepicker-switch':
+ this.showMode(1);
+ break;
+ case 'prev':
+ case 'next':
+ var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
+ switch(this.viewMode){
+ case 0:
+ this.viewDate = this.moveMonth(this.viewDate, dir);
+ break;
+ case 1:
+ case 2:
+ this.viewDate = this.moveYear(this.viewDate, dir);
+ break;
+ }
+ this.fill();
+ break;
+ case 'today':
+ var date = new Date();
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
+
+ this.showMode(-2);
+ var which = this.o.todayBtn == 'linked' ? null : 'view';
+ this._setDate(date, which);
+ break;
+ case 'clear':
+ if (this.isInput)
+ this.element.val("");
+ else
+ this.element.find('input').val("");
+ this.update();
+ if (this.o.autoclose)
+ this.hide();
+ break;
+ }
+ break;
+ case 'span':
+ if (!target.is('.disabled')) {
+ this.viewDate.setUTCDate(1);
+ if (target.is('.month')) {
+ var day = 1;
+ var month = target.parent().find('span').index(target);
+ var year = this.viewDate.getUTCFullYear();
+ this.viewDate.setUTCMonth(month);
+ this._trigger('changeMonth', this.viewDate);
+ if (this.o.minViewMode === 1) {
+ this._setDate(UTCDate(year, month, day,0,0,0,0));
+ }
+ } else {
+ var year = parseInt(target.text(), 10)||0;
+ var day = 1;
+ var month = 0;
+ this.viewDate.setUTCFullYear(year);
+ this._trigger('changeYear', this.viewDate);
+ if (this.o.minViewMode === 2) {
+ this._setDate(UTCDate(year, month, day,0,0,0,0));
+ }
+ }
+ this.showMode(-1);
+ this.fill();
+ }
+ break;
+ case 'td':
+ if (target.is('.day') && !target.is('.disabled')){
+ var day = parseInt(target.text(), 10)||1;
+ var year = this.viewDate.getUTCFullYear(),
+ month = this.viewDate.getUTCMonth();
+ if (target.is('.old')) {
+ if (month === 0) {
+ month = 11;
+ year -= 1;
+ } else {
+ month -= 1;
+ }
+ } else if (target.is('.new')) {
+ if (month == 11) {
+ month = 0;
+ year += 1;
+ } else {
+ month += 1;
+ }
+ }
+ this._setDate(UTCDate(year, month, day,0,0,0,0));
+ }
+ break;
+ }
+ }
+ },
+
+ _setDate: function(date, which){
+ if (!which || which == 'date')
+ this.date = new Date(date);
+ if (!which || which == 'view')
+ this.viewDate = new Date(date);
+ this.fill();
+ this.setValue();
+ this._trigger('changeDate');
+ var element;
+ if (this.isInput) {
+ element = this.element;
+ } else if (this.component){
+ element = this.element.find('input');
+ }
+ if (element) {
+ element.change();
+ if (this.o.autoclose && (!which || which == 'date')) {
+ this.hide();
+ }
+ }
+ },
+
+ moveMonth: function(date, dir){
+ if (!dir) return date;
+ var new_date = new Date(date.valueOf()),
+ day = new_date.getUTCDate(),
+ month = new_date.getUTCMonth(),
+ mag = Math.abs(dir),
+ new_month, test;
+ dir = dir > 0 ? 1 : -1;
+ if (mag == 1){
+ test = dir == -1
+ // If going back one month, make sure month is not current month
+ // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
+ ? function(){ return new_date.getUTCMonth() == month; }
+ // If going forward one month, make sure month is as expected
+ // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
+ : function(){ return new_date.getUTCMonth() != new_month; };
+ new_month = month + dir;
+ new_date.setUTCMonth(new_month);
+ // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
+ if (new_month < 0 || new_month > 11)
+ new_month = (new_month + 12) % 12;
+ } else {
+ // For magnitudes >1, move one month at a time...
+ for (var i=0; i= this.o.startDate && date <= this.o.endDate;
+ },
+
+ keydown: function(e){
+ if (this.picker.is(':not(:visible)')){
+ if (e.keyCode == 27) // allow escape to hide and re-show picker
+ this.show();
+ return;
+ }
+ var dateChanged = false,
+ dir, day, month,
+ newDate, newViewDate;
+ switch(e.keyCode){
+ case 27: // escape
+ this.hide();
+ e.preventDefault();
+ break;
+ case 37: // left
+ case 39: // right
+ if (!this.o.keyboardNavigation) break;
+ dir = e.keyCode == 37 ? -1 : 1;
+ if (e.ctrlKey){
+ newDate = this.moveYear(this.date, dir);
+ newViewDate = this.moveYear(this.viewDate, dir);
+ } else if (e.shiftKey){
+ newDate = this.moveMonth(this.date, dir);
+ newViewDate = this.moveMonth(this.viewDate, dir);
+ } else {
+ newDate = new Date(this.date);
+ newDate.setUTCDate(this.date.getUTCDate() + dir);
+ newViewDate = new Date(this.viewDate);
+ newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
+ }
+ if (this.dateWithinRange(newDate)){
+ this.date = newDate;
+ this.viewDate = newViewDate;
+ this.setValue();
+ this.update();
+ e.preventDefault();
+ dateChanged = true;
+ }
+ break;
+ case 38: // up
+ case 40: // down
+ if (!this.o.keyboardNavigation) break;
+ dir = e.keyCode == 38 ? -1 : 1;
+ if (e.ctrlKey){
+ newDate = this.moveYear(this.date, dir);
+ newViewDate = this.moveYear(this.viewDate, dir);
+ } else if (e.shiftKey){
+ newDate = this.moveMonth(this.date, dir);
+ newViewDate = this.moveMonth(this.viewDate, dir);
+ } else {
+ newDate = new Date(this.date);
+ newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
+ newViewDate = new Date(this.viewDate);
+ newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
+ }
+ if (this.dateWithinRange(newDate)){
+ this.date = newDate;
+ this.viewDate = newViewDate;
+ this.setValue();
+ this.update();
+ e.preventDefault();
+ dateChanged = true;
+ }
+ break;
+ case 13: // enter
+ this.hide();
+ e.preventDefault();
+ break;
+ case 9: // tab
+ this.hide();
+ break;
+ }
+ if (dateChanged){
+ this._trigger('changeDate');
+ var element;
+ if (this.isInput) {
+ element = this.element;
+ } else if (this.component){
+ element = this.element.find('input');
+ }
+ if (element) {
+ element.change();
+ }
+ }
+ },
+
+ showMode: function(dir) {
+ if (dir) {
+ this.viewMode = Math.max(this.o.minViewMode, Math.min(2, this.viewMode + dir));
+ }
+ /*
+ vitalets: fixing bug of very special conditions:
+ jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover.
+ Method show() does not set display css correctly and datepicker is not shown.
+ Changed to .css('display', 'block') solve the problem.
+ See https://github.com/vitalets/x-editable/issues/37
+
+ In jquery 1.7.2+ everything works fine.
+ */
+ //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
+ this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
+ this.updateNavArrows();
+ }
+ };
+
+ var DateRangePicker = function(element, options){
+ this.element = $(element);
+ this.inputs = $.map(options.inputs, function(i){ return i.jquery ? i[0] : i; });
+ delete options.inputs;
+
+ $(this.inputs)
+ .datepicker(options)
+ .bind('changeDate', $.proxy(this.dateUpdated, this));
+
+ this.pickers = $.map(this.inputs, function(i){ return $(i).data('datepicker'); });
+ this.updateDates();
+ };
+ DateRangePicker.prototype = {
+ updateDates: function(){
+ this.dates = $.map(this.pickers, function(i){ return i.date; });
+ this.updateRanges();
+ },
+ updateRanges: function(){
+ var range = $.map(this.dates, function(d){ return d.valueOf(); });
+ $.each(this.pickers, function(i, p){
+ p.setRange(range);
+ });
+ },
+ dateUpdated: function(e){
+ var dp = $(e.target).data('datepicker'),
+ new_date = dp.getUTCDate(),
+ i = $.inArray(e.target, this.inputs),
+ l = this.inputs.length;
+ if (i == -1) return;
+
+ if (new_date < this.dates[i]){
+ // Date being moved earlier/left
+ while (i>=0 && new_date < this.dates[i]){
+ this.pickers[i--].setUTCDate(new_date);
+ }
+ }
+ else if (new_date > this.dates[i]){
+ // Date being moved later/right
+ while (i this.dates[i]){
+ this.pickers[i++].setUTCDate(new_date);
+ }
+ }
+ this.updateDates();
+ },
+ remove: function(){
+ $.map(this.pickers, function(p){ p.remove(); });
+ delete this.element.data().datepicker;
+ }
+ };
+
+ function opts_from_el(el, prefix){
+ // Derive options from element data-attrs
+ var data = $(el).data(),
+ out = {}, inkey,
+ replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])'),
+ prefix = new RegExp('^' + prefix.toLowerCase());
+ for (var key in data)
+ if (prefix.test(key)){
+ inkey = key.replace(replace, function(_,a){ return a.toLowerCase(); });
+ out[inkey] = data[key];
+ }
+ return out;
+ }
+
+ function opts_from_locale(lang){
+ // Derive options from locale plugins
+ var out = {};
+ // Check if "de-DE" style date is available, if not language should
+ // fallback to 2 letter code eg "de"
+ if (!dates[lang]) {
+ lang = lang.split('-')[0]
+ if (!dates[lang])
+ return;
+ }
+ var d = dates[lang];
+ $.each($.fn.datepicker.locale_opts, function(i,k){
+ if (k in d)
+ out[k] = d[k];
+ });
+ return out;
+ }
+
+ var old = $.fn.datepicker;
+ $.fn.datepicker = function ( option ) {
+ var args = Array.apply(null, arguments);
+ args.shift();
+ var internal_return,
+ this_return;
+ this.each(function () {
+ var $this = $(this),
+ data = $this.data('datepicker'),
+ options = typeof option == 'object' && option;
+ if (!data) {
+ var elopts = opts_from_el(this, 'date'),
+ // Preliminary otions
+ xopts = $.extend({}, $.fn.datepicker.defaults, elopts, options),
+ locopts = opts_from_locale(xopts.language),
+ // Options priority: js args, data-attrs, locales, defaults
+ opts = $.extend({}, $.fn.datepicker.defaults, locopts, elopts, options);
+ if ($this.is('.input-daterange') || opts.inputs){
+ var ropts = {
+ inputs: opts.inputs || $this.find('input').toArray()
+ };
+ $this.data('datepicker', (data = new DateRangePicker(this, $.extend(opts, ropts))));
+ }
+ else{
+ $this.data('datepicker', (data = new Datepicker(this, opts)));
+ }
+ }
+ if (typeof option == 'string' && typeof data[option] == 'function') {
+ internal_return = data[option].apply(data, args);
+ if (internal_return !== undefined)
+ return false;
+ }
+ });
+ if (internal_return !== undefined)
+ return internal_return;
+ else
+ return this;
+ };
+
+ $.fn.datepicker.defaults = {
+ autoclose: false,
+ beforeShowDay: $.noop,
+ calendarWeeks: false,
+ clearBtn: false,
+ daysOfWeekDisabled: [],
+ endDate: Infinity,
+ forceParse: true,
+ format: 'mm/dd/yyyy',
+ keyboardNavigation: true,
+ language: 'en',
+ minViewMode: 0,
+ rtl: false,
+ startDate: -Infinity,
+ startView: 0,
+ todayBtn: false,
+ todayHighlight: false,
+ weekStart: 0
+ };
+ $.fn.datepicker.locale_opts = [
+ 'format',
+ 'rtl',
+ 'weekStart'
+ ];
+ $.fn.datepicker.Constructor = Datepicker;
+ var dates = $.fn.datepicker.dates = {
+ en: {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ clear: "Clear"
+ }
+ };
+
+ var DPGlobal = {
+ modes: [
+ {
+ clsName: 'days',
+ navFnc: 'Month',
+ navStep: 1
+ },
+ {
+ clsName: 'months',
+ navFnc: 'FullYear',
+ navStep: 1
+ },
+ {
+ clsName: 'years',
+ navFnc: 'FullYear',
+ navStep: 10
+ }],
+ isLeapYear: function (year) {
+ return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
+ },
+ getDaysInMonth: function (year, month) {
+ return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
+ },
+ validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
+ nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
+ parseFormat: function(format){
+ // IE treats \0 as a string end in inputs (truncating the value),
+ // so it's a bad format delimiter, anyway
+ var separators = format.replace(this.validParts, '\0').split('\0'),
+ parts = format.match(this.validParts);
+ if (!separators || !separators.length || !parts || parts.length === 0){
+ throw new Error("Invalid date format.");
+ }
+ return {separators: separators, parts: parts};
+ },
+ parseDate: function(date, format, language) {
+ if (date instanceof Date) return date;
+ if (typeof format === 'string')
+ format = DPGlobal.parseFormat(format);
+ if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)) {
+ var part_re = /([\-+]\d+)([dmwy])/,
+ parts = date.match(/([\-+]\d+)([dmwy])/g),
+ part, dir;
+ date = new Date();
+ for (var i=0; i'+
+ '
'
+ };
+
+ $.fn.modalmanager.Constructor = ModalManager
+
+}(jQuery);
diff --git a/mall-master/src/main/resources/static/js/bootstrap-rtl.min.js b/mall-master/src/main/resources/static/js/bootstrap-rtl.min.js
new file mode 100644
index 0000000..e69de29
diff --git a/mall-master/src/main/resources/static/js/bootstrap-tag.js b/mall-master/src/main/resources/static/js/bootstrap-tag.js
new file mode 100644
index 0000000..76b1de0
--- /dev/null
+++ b/mall-master/src/main/resources/static/js/bootstrap-tag.js
@@ -0,0 +1,246 @@
+/* ==========================================================
+ * bootstrap-tag.js v2.2.2
+ * https://github.com/fdeschenes/bootstrap-tag
+ * ==========================================================
+ * Copyright 2012 Francois Deschenes.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+// https://github.com/soliantconsulting/tagmanager/blob/master/tagmanager.js
+
+!function ( $ ) {
+
+ 'use strict' // jshint ;_;
+
+ var Tag = function ( element, options ) {
+ this.element = $(element)
+ this.options = $.extend(true, {}, $.fn.tag.defaults, options)
+ this.values = $.grep($.map(this.element.val().split(','), $.trim), function ( value ) { return value.length > 0 })
+ this.show()
+ }
+
+ Tag.prototype = {
+ constructor: Tag
+
+ , show: function () {
+ var that = this
+
+ that.element.parent().prepend(that.element.detach().attr('type', 'hidden'))
+ that.element
+ .wrap($('
'))
+ .parent()
+ .on('click', function () {
+ that.input.focus()
+ })
+
+ if (that.values.length) {
+ $.each(that.values, function () {
+ that.createBadge(this)
+ })
+ }
+
+
+ that.input = $('')
+ .attr('placeholder', that.options.placeholder)
+ .insertAfter(that.element)
+ .on('focus', function () {
+ that.element.parent().addClass('tags-hover')
+ })
+ .on('blur', function () {
+ that.process()
+ that.element.parent().removeClass('tags-hover')
+ that.element.siblings('.tag').removeClass('tag-important')
+ })
+ .on('keydown', function ( event ) {
+ if ( event.keyCode == 188 || event.keyCode == 13 || event.keyCode == 9 ) {
+ if ( $.trim($(this).val()) && ( !that.element.siblings('.typeahead').length || that.element.siblings('.typeahead').is(':hidden') ) ) {
+ if ( event.keyCode != 9 ) event.preventDefault()
+ that.process()
+ } else if ( event.keyCode == 188 ) {
+ if ( !that.element.siblings('.typeahead').length || that.element.siblings('.typeahead').is(':hidden') ) {
+ event.preventDefault()
+ } else {
+ that.input.data('typeahead').select()
+ event.stopPropagation()
+ event.preventDefault()
+ }
+ }
+ } else if ( !$.trim($(this).val()) && event.keyCode == 8 ) {
+ var count = that.element.siblings('.tag').length
+ if (count) {
+ var tag = that.element.siblings('.tag:eq(' + (count - 1) + ')')
+ if (tag.hasClass('tag-important')) that.remove(count - 1)
+ else tag.addClass('tag-important')
+ }
+ } else {
+ that.element.siblings('.tag').removeClass('tag-important')
+ }
+ })
+ .typeahead({
+ source: that.options.source
+ , matcher: function ( value ) {
+ return ~value.toLowerCase().indexOf(this.query.toLowerCase()) && (that.inValues(value) == -1 || that.options.allowDuplicates)
+ }
+ , updater: $.proxy(that.add, that)
+ });
+
+
+ //auto resize input: this option added by keenthemes for inbos compose form needs. this will enable typing a tag in hirozontal position and input auto resizes while typing
+ if (that.options.autosizedInput) {
+ var input = that.input,
+ minWidth = that.options.minWidth || input.width(),
+ maxWidth = that.options.maxWidth || input.closest(".tags").width(),
+ comfortZone = 10,
+ val = '',
+
+ testSubject = $('').css({
+ position: 'absolute',
+ top: -9999,
+ left: -9999,
+ width: 'auto',
+ paddingLeft: input.css('paddingLeft'),
+ paddingRight: input.css('paddingRight'),
+ fontSize: input.css('fontSize'),
+ fontFamily: input.css('fontFamily'),
+ fontWeight: input.css('fontWeight'),
+ letterSpacing: input.css('letterSpacing'),
+ whiteSpace: 'nowrap'
+ }),
+
+ check = function() {
+
+ if (val === (val = input.val())) {return;}
+
+ // Enter new content into testSubject
+ var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(//g, '>');
+ testSubject.html(escaped);
+
+ // Calculate new width + whether to change
+ var testerWidth = testSubject.width(),
+ newWidth = (testerWidth + comfortZone) >= minWidth ? testerWidth + comfortZone : minWidth,
+ currentWidth = input.width(),
+ isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)
+ || (newWidth > minWidth && newWidth < maxWidth);
+
+
+ // Animate width
+ if (isValidWidthChange) {
+ input.width(newWidth);
+ }
+
+ };
+
+ testSubject.insertAfter(input);
+
+ input.bind('keydown keyup blur update', check);
+ }
+ //auto resize input: added by keenthemes
+ }
+ , inValues: function ( value ) {
+ if (this.options.caseInsensitive) {
+ var index = -1
+ $.each(this.values, function (indexInArray, valueOfElement) {
+ if ( valueOfElement.toLowerCase() == value.toLowerCase() ) {
+ index = indexInArray
+ return false
+ }
+ })
+ return index
+ } else {
+ return $.inArray(value, this.values)
+ }
+ }
+ , createBadge: function ( value ) {
+ var that = this
+
+ $('')
+ .text(value)
+ .append($('') //modified by keenthemes sinse close class already defined in global style(style.css)
+ .on('click', function () {
+ that.remove(that.element.siblings('.tag').index($(this).closest('.tag')))
+ })
+ )
+ .insertBefore(that.element)
+ }
+ , add: function ( value ) {
+ var that = this
+
+ if ( !that.options.allowDuplicates ) {
+ var index = that.inValues(value)
+ if ( index != -1 ) {
+ var badge = that.element.siblings('.tag:eq(' + index + ')')
+ badge.addClass('tag-warning')
+ setTimeout(function () {
+ $(badge).removeClass('tag-warning')
+ }, 500)
+ return
+ }
+ }
+
+ this.values.push(value)
+ this.createBadge(value)
+
+ this.element.val(this.values.join(', '))
+ }
+ , remove: function ( index ) {
+ if ( index >= 0 ) {
+ this.values.splice(index, 1)
+ this.element.siblings('.tag:eq(' + index + ')').remove()
+ this.element.val(this.values.join(', '))
+ }
+ }
+ , process: function () {
+ var values = $.grep($.map(this.input.val().split(','), $.trim), function ( value ) { return value.length > 0 }),
+ that = this
+ $.each(values, function() {
+ that.add(this)
+ })
+ this.input.val('')
+ }
+ }
+
+ var old = $.fn.tag
+
+ $.fn.tag = function ( option ) {
+ return this.each(function () {
+ var that = $(this)
+ , data = that.data('tag')
+ , options = typeof option == 'object' && option
+ if (!data) that.data('tag', (data = new Tag(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tag.defaults = {
+ allowDuplicates: false
+ , caseInsensitive: true
+ , placeholder: ''
+ , source: []
+ }
+
+ $.fn.tag.Constructor = Tag
+
+ $.fn.tag.noConflict = function () {
+ $.fn.tag = old
+ return this
+ }
+
+ $(window).on('load', function () {
+ $('[data-provide="tag"]').each(function () {
+ var that = $(this)
+ if (that.data('tag')) return
+ that.tag(that.data())
+ })
+ })
+}(window.jQuery)
\ No newline at end of file
diff --git a/mall-master/src/main/resources/static/js/bootstrap-timepicker.js b/mall-master/src/main/resources/static/js/bootstrap-timepicker.js
new file mode 100644
index 0000000..3e10ca2
--- /dev/null
+++ b/mall-master/src/main/resources/static/js/bootstrap-timepicker.js
@@ -0,0 +1,803 @@
+/* =========================================================
+ * bootstrap-timepicker.js
+ * http://www.github.com/jdewit/bootstrap-timepicker
+ * =========================================================
+ * Copyright 2012
+ *
+ * Created By:
+ * Joris de Wit @joris_dewit
+ *
+ * Contributions By:
+ * Gilbert @mindeavor
+ * Koen Punt info@koenpunt.nl
+ * Nek
+ * Chris Martin
+ * Dominic Barnes contact@dominicbarnes.us
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+!function($) {
+
+ "use strict"; // jshint ;_;
+
+ /* TIMEPICKER PUBLIC CLASS DEFINITION
+ * ================================== */
+ var Timepicker = function(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, $.fn.timepicker.defaults, options, this.$element.data());
+ this.minuteStep = this.options.minuteStep || this.minuteStep;
+ this.secondStep = this.options.secondStep || this.secondStep;
+ this.showMeridian = this.options.showMeridian || this.showMeridian;
+ this.showSeconds = this.options.showSeconds || this.showSeconds;
+ this.showInputs = this.options.showInputs || this.showInputs;
+ this.disableFocus = this.options.disableFocus || this.disableFocus;
+ this.template = this.options.template || this.template;
+ this.modalBackdrop = this.options.modalBackdrop || this.modalBackdrop;
+ this.defaultTime = this.options.defaultTime || this.defaultTime;
+ this.open = false;
+ this.init();
+ };
+
+ Timepicker.prototype = {
+
+ constructor: Timepicker
+
+ , init: function () {
+ if (this.$element.parent().hasClass('input-append')) {
+ this.$element.parent('.input-append').find('.add-on').on('click', $.proxy(this.showWidget, this));
+ this.$element.on({
+ focus: $.proxy(this.highlightUnit, this),
+ click: $.proxy(this.highlightUnit, this),
+ keypress: $.proxy(this.elementKeypress, this),
+ blur: $.proxy(this.blurElement, this)
+ });
+
+ } else {
+ if (this.template) {
+ this.$element.on({
+ focus: $.proxy(this.showWidget, this),
+ click: $.proxy(this.showWidget, this),
+ blur: $.proxy(this.blurElement, this)
+ });
+ } else {
+ this.$element.on({
+ focus: $.proxy(this.highlightUnit, this),
+ click: $.proxy(this.highlightUnit, this),
+ keypress: $.proxy(this.elementKeypress, this),
+ blur: $.proxy(this.blurElement, this)
+ });
+ }
+ }
+
+
+ this.$widget = $(this.getTemplate()).appendTo('body');
+
+ this.$widget.on('click', $.proxy(this.widgetClick, this));
+
+ if (this.showInputs) {
+ this.$widget.find('input').on({
+ click: function() { this.select(); },
+ keypress: $.proxy(this.widgetKeypress, this),
+ change: $.proxy(this.updateFromWidgetInputs, this)
+ });
+ }
+
+ this.setDefaultTime(this.defaultTime);
+ }
+
+ , showWidget: function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ if (this.open) {
+ return;
+ }
+
+ this.$element.trigger('show');
+
+ if (this.disableFocus) {
+ this.$element.blur();
+ }
+
+ var pos = $.extend({}, this.$element.offset(), {
+ height: this.$element[0].offsetHeight
+ });
+
+ this.updateFromElementVal();
+
+ $('html')
+ .trigger('click.timepicker.data-api')
+ .one('click.timepicker.data-api', $.proxy(this.hideWidget, this));
+
+ if (this.template === 'modal') {
+ this.$widget.modal('show').on('hidden', $.proxy(this.hideWidget, this));
+ } else {
+ this.$widget.css({
+ top: pos.top + pos.height
+ , left: pos.left
+ })
+
+ if (!this.open) {
+ this.$widget.addClass('open');
+ }
+ }
+
+ this.open = true;
+ this.$element.trigger('shown');
+ }
+
+ , hideWidget: function(){
+ this.$element.trigger('hide');
+
+ if (this.template === 'modal') {
+ this.$widget.modal('hide');
+ } else {
+ this.$widget.removeClass('open');
+ }
+ this.open = false;
+ this.$element.trigger('hidden');
+ }
+
+ , widgetClick: function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ var action = $(e.target).closest('a').data('action');
+ if (action) {
+ this[action]();
+ this.update();
+ }
+ }
+
+ , widgetKeypress: function(e) {
+ var input = $(e.target).closest('input').attr('name');
+
+ switch (e.keyCode) {
+ case 9: //tab
+ if (this.showMeridian) {
+ if (input == 'meridian') {
+ this.hideWidget();
+ }
+ } else {
+ if (this.showSeconds) {
+ if (input == 'second') {
+ this.hideWidget();
+ }
+ } else {
+ if (input == 'minute') {
+ this.hideWidget();
+ }
+ }
+ }
+ break;
+ case 27: // escape
+ this.hideWidget();
+ break;
+ case 38: // up arrow
+ switch (input) {
+ case 'hour':
+ this.incrementHour();
+ break;
+ case 'minute':
+ this.incrementMinute();
+ break;
+ case 'second':
+ this.incrementSecond();
+ break;
+ case 'meridian':
+ this.toggleMeridian();
+ break;
+ }
+ this.update();
+ break;
+ case 40: // down arrow
+ switch (input) {
+ case 'hour':
+ this.decrementHour();
+ break;
+ case 'minute':
+ this.decrementMinute();
+ break;
+ case 'second':
+ this.decrementSecond();
+ break;
+ case 'meridian':
+ this.toggleMeridian();
+ break;
+ }
+ this.update();
+ break;
+ }
+ }
+
+ , elementKeypress: function(e) {
+ var input = this.$element.get(0);
+ switch (e.keyCode) {
+ case 0: //input
+ break;
+ case 9: //tab
+ this.updateFromElementVal();
+ if (this.showMeridian) {
+ if (this.highlightedUnit != 'meridian') {
+ e.preventDefault();
+ this.highlightNextUnit();
+ }
+ } else {
+ if (this.showSeconds) {
+ if (this.highlightedUnit != 'second') {
+ e.preventDefault();
+ this.highlightNextUnit();
+ }
+ } else {
+ if (this.highlightedUnit != 'minute') {
+ e.preventDefault();
+ this.highlightNextUnit();
+ }
+ }
+ }
+ break;
+ case 27: // escape
+ this.updateFromElementVal();
+ break;
+ case 37: // left arrow
+ this.updateFromElementVal();
+ this.highlightPrevUnit();
+ break;
+ case 38: // up arrow
+ switch (this.highlightedUnit) {
+ case 'hour':
+ this.incrementHour();
+ break;
+ case 'minute':
+ this.incrementMinute();
+ break;
+ case 'second':
+ this.incrementSecond();
+ break;
+ case 'meridian':
+ this.toggleMeridian();
+ break;
+ }
+ this.updateElement();
+ break;
+ case 39: // right arrow
+ this.updateFromElementVal();
+ this.highlightNextUnit();
+ break;
+ case 40: // down arrow
+ switch (this.highlightedUnit) {
+ case 'hour':
+ this.decrementHour();
+ break;
+ case 'minute':
+ this.decrementMinute();
+ break;
+ case 'second':
+ this.decrementSecond();
+ break;
+ case 'meridian':
+ this.toggleMeridian();
+ break;
+ }
+ this.updateElement();
+ break;
+ }
+
+ if (e.keyCode !== 0 && e.keyCode !== 8 && e.keyCode !== 9 && e.keyCode !== 46) {
+ e.preventDefault();
+ }
+ }
+
+ , setValues: function(time) {
+ if (this.showMeridian) {
+ var arr = time.split(' ');
+ var timeArray = arr[0].split(':');
+ this.meridian = arr[1];
+ } else {
+ var timeArray = time.split(':');
+ }
+
+ this.hour = parseInt(timeArray[0], 10);
+ this.minute = parseInt(timeArray[1], 10);
+ this.second = parseInt(timeArray[2], 10);
+
+ if (isNaN(this.hour)) {
+ this.hour = 0;
+ }
+ if (isNaN(this.minute)) {
+ this.minute = 0;
+ }
+
+ if (this.showMeridian) {
+ if (this.hour > 12) {
+ this.hour = 12;
+ } else if (this.hour < 1) {
+ this.hour = 1;
+ }
+
+ if (this.meridian == 'am' || this.meridian == 'a') {
+ this.meridian = 'AM';
+ } else if (this.meridian == 'pm' || this.meridian == 'p') {
+ this.meridian = 'PM';
+ }
+
+ if (this.meridian != 'AM' && this.meridian != 'PM') {
+ this.meridian = 'AM';
+ }
+ } else {
+ if (this.hour >= 24) {
+ this.hour = 23;
+ } else if (this.hour < 0) {
+ this.hour = 0;
+ }
+ }
+
+ if (this.minute < 0) {
+ this.minute = 0;
+ } else if (this.minute >= 60) {
+ this.minute = 59;
+ }
+
+ if (this.showSeconds) {
+ if (isNaN(this.second)) {
+ this.second = 0;
+ } else if (this.second < 0) {
+ this.second = 0;
+ } else if (this.second >= 60) {
+ this.second = 59;
+ }
+ }
+
+ if ( this.$element.val() != '' )
+ this.updateElement();
+ this.updateWidget();
+ }
+
+ , setMeridian: function(meridian) {
+ if (meridian == 'a' || meridian == 'am' || meridian == 'AM' ) {
+ this.meridian = 'AM';
+ } else if (meridian == 'p' || meridian == 'pm' || meridian == 'PM' ) {
+ this.meridian = 'PM';
+ } else {
+ this.updateWidget();
+ }
+
+ this.updateElement();
+ }
+
+ , setDefaultTime: function(defaultTime){
+ if (defaultTime) {
+ if (defaultTime === 'current') {
+ var dTime = new Date();
+ var hours = dTime.getHours();
+ var minutes = Math.floor(dTime.getMinutes() / this.minuteStep) * this.minuteStep;
+ var seconds = Math.floor(dTime.getSeconds() / this.secondStep) * this.secondStep;
+ var meridian = "AM";
+ if (this.showMeridian) {
+ if (hours === 0) {
+ hours = 12;
+ } else if (hours >= 12) {
+ if (hours > 12) {
+ hours = hours - 12;
+ }
+ meridian = "PM";
+ } else {
+ meridian = "AM";
+ }
+ }
+ this.hour = hours;
+ this.minute = minutes;
+ this.second = seconds;
+ this.meridian = meridian;
+ } else if (defaultTime === 'value') {
+ this.setValues(this.$element.val());
+ } else {
+ this.setValues(defaultTime);
+ }
+ if ( this.$element.val() != '' )
+ this.updateElement();
+ this.updateWidget();
+ } else {
+ this.hour = 0;
+ this.minute = 0;
+ this.second = 0;
+ }
+ }
+
+ , formatTime: function(hour, minute, second, meridian) {
+ hour = hour < 10 ? '0' + hour : hour;
+ minute = minute < 10 ? '0' + minute : minute;
+ second = second < 10 ? '0' + second : second;
+
+ return hour + ':' + minute + (this.showSeconds ? ':' + second : '') + (this.showMeridian ? ' ' + meridian : '');
+ }
+
+ , getTime: function() {
+ return this.formatTime(this.hour, this.minute, this.second, this.meridian);
+ }
+
+ , setTime: function(time) {
+ this.setValues(time);
+ this.update();
+ }
+
+ , update: function() {
+ this.updateElement();
+ this.updateWidget();
+ }
+
+ , blurElement: function() {
+ this.highlightedUnit = undefined;
+ this.updateFromElementVal();
+ }
+
+ , updateElement: function() {
+ var time = this.getTime();
+
+ this.$element.val(time).change();
+
+ switch (this.highlightedUnit) {
+ case 'hour':
+ this.highlightHour();
+ break;
+ case 'minute':
+ this.highlightMinute();
+ break;
+ case 'second':
+ this.highlightSecond();
+ break;
+ case 'meridian':
+ this.highlightMeridian();
+ break;
+ }
+ }
+
+ , updateWidget: function() {
+ if (this.showInputs) {
+ this.$widget.find('input.bootstrap-timepicker-hour').val(this.hour < 10 ? '0' + this.hour : this.hour);
+ this.$widget.find('input.bootstrap-timepicker-minute').val(this.minute < 10 ? '0' + this.minute : this.minute);
+ if (this.showSeconds) {
+ this.$widget.find('input.bootstrap-timepicker-second').val(this.second < 10 ? '0' + this.second : this.second);
+ }
+ if (this.showMeridian) {
+ this.$widget.find('input.bootstrap-timepicker-meridian').val(this.meridian);
+ }
+ } else {
+ this.$widget.find('span.bootstrap-timepicker-hour').text(this.hour);
+ this.$widget.find('span.bootstrap-timepicker-minute').text(this.minute < 10 ? '0' + this.minute : this.minute);
+ if (this.showSeconds) {
+ this.$widget.find('span.bootstrap-timepicker-second').text(this.second < 10 ? '0' + this.second : this.second);
+ }
+ if (this.showMeridian) {
+ this.$widget.find('span.bootstrap-timepicker-meridian').text(this.meridian);
+ }
+ }
+ }
+
+ , updateFromElementVal: function (e) {
+ var time = this.$element.val();
+ if (time) {
+ this.setValues(time);
+ this.updateWidget();
+ }
+ }
+
+ , updateFromWidgetInputs: function () {
+ var time = $('input.bootstrap-timepicker-hour', this.$widget).val() + ':' +
+ $('input.bootstrap-timepicker-minute', this.$widget).val() +
+ (this.showSeconds ?
+ ':' + $('input.bootstrap-timepicker-second', this.$widget).val()
+ : '') +
+ (this.showMeridian ?
+ ' ' + $('input.bootstrap-timepicker-meridian', this.$widget).val()
+ : '');
+
+ this.setValues(time);
+ }
+
+ , getCursorPosition: function() {
+ var input = this.$element.get(0);
+
+ if ('selectionStart' in input) {
+ // Standard-compliant browsers
+ return input.selectionStart;
+ } else if (document.selection) {
+ // IE fix
+ input.focus();
+ var sel = document.selection.createRange();
+ var selLen = document.selection.createRange().text.length;
+ sel.moveStart('character', - input.value.length);
+
+ return sel.text.length - selLen;
+ }
+ }
+
+ , highlightUnit: function () {
+ var input = this.$element.get(0);
+
+ this.position = this.getCursorPosition();
+ if (this.position >= 0 && this.position <= 2) {
+ this.highlightHour();
+ } else if (this.position >= 3 && this.position <= 5) {
+ this.highlightMinute();
+ } else if (this.position >= 6 && this.position <= 8) {
+ if (this.showSeconds) {
+ this.highlightSecond();
+ } else {
+ this.highlightMeridian();
+ }
+ } else if (this.position >= 9 && this.position <= 11) {
+ this.highlightMeridian();
+ }
+ }
+
+ , highlightNextUnit: function() {
+ switch (this.highlightedUnit) {
+ case 'hour':
+ this.highlightMinute();
+ break;
+ case 'minute':
+ if (this.showSeconds) {
+ this.highlightSecond();
+ } else {
+ this.highlightMeridian();
+ }
+ break;
+ case 'second':
+ this.highlightMeridian();
+ break;
+ case 'meridian':
+ this.highlightHour();
+ break;
+ }
+ }
+
+ , highlightPrevUnit: function() {
+ switch (this.highlightedUnit) {
+ case 'hour':
+ this.highlightMeridian();
+ break;
+ case 'minute':
+ this.highlightHour();
+ break;
+ case 'second':
+ this.highlightMinute();
+ break;
+ case 'meridian':
+ if (this.showSeconds) {
+ this.highlightSecond();
+ } else {
+ this.highlightMinute();
+ }
+ break;
+ }
+ }
+
+ , highlightHour: function() {
+ this.highlightedUnit = 'hour';
+ this.$element.get(0).setSelectionRange(0,2);
+ }
+
+ , highlightMinute: function() {
+ this.highlightedUnit = 'minute';
+ this.$element.get(0).setSelectionRange(3,5);
+ }
+
+ , highlightSecond: function() {
+ this.highlightedUnit = 'second';
+ this.$element.get(0).setSelectionRange(6,8);
+ }
+
+ , highlightMeridian: function() {
+ this.highlightedUnit = 'meridian';
+ if (this.showSeconds) {
+ this.$element.get(0).setSelectionRange(9,11);
+ } else {
+ this.$element.get(0).setSelectionRange(6,8);
+ }
+ }
+
+ , incrementHour: function() {
+ if (this.showMeridian) {
+ if (this.hour === 11) {
+ this.toggleMeridian();
+ } else if (this.hour === 12) {
+ return this.hour = 1;
+ }
+ }
+ if (this.hour === 23) {
+ return this.hour = 0;
+ }
+ this.hour = this.hour + 1;
+ }
+
+ , decrementHour: function() {
+ if (this.showMeridian) {
+ if (this.hour === 1) {
+ return this.hour = 12;
+ }
+ else if (this.hour === 12) {
+ this.toggleMeridian();
+ }
+ }
+ if (this.hour === 0) {
+ return this.hour = 23;
+ }
+ this.hour = this.hour - 1;
+ }
+
+ , incrementMinute: function() {
+ var newVal = this.minute + this.minuteStep - (this.minute % this.minuteStep);
+ if (newVal > 59) {
+ this.incrementHour();
+ this.minute = newVal - 60;
+ } else {
+ this.minute = newVal;
+ }
+ }
+
+ , decrementMinute: function() {
+ var newVal = this.minute - this.minuteStep;
+ if (newVal < 0) {
+ this.decrementHour();
+ this.minute = newVal + 60;
+ } else {
+ this.minute = newVal;
+ }
+ }
+
+ , incrementSecond: function() {
+ var newVal = this.second + this.secondStep - (this.second % this.secondStep);
+ if (newVal > 59) {
+ this.incrementMinute();
+ this.second = newVal - 60;
+ } else {
+ this.second = newVal;
+ }
+ }
+
+ , decrementSecond: function() {
+ var newVal = this.second - this.secondStep;
+ if (newVal < 0) {
+ this.decrementMinute();
+ this.second = newVal + 60;
+ } else {
+ this.second = newVal;
+ }
+ }
+
+ , toggleMeridian: function() {
+ this.meridian = this.meridian === 'AM' ? 'PM' : 'AM';
+
+ this.update();
+ }
+
+ , getTemplate: function() {
+ if (this.options.templates[this.options.template]) {
+ return this.options.templates[this.options.template];
+ }
+ if (this.showInputs) {
+ var hourTemplate = '';
+ var minuteTemplate = '';
+ var secondTemplate = '';
+ var meridianTemplate = '';
+ } else {
+ var hourTemplate = '';
+ var minuteTemplate = '';
+ var secondTemplate = '';
+ var meridianTemplate = '';
+ }
+ var templateContent = '
'+
+ '
'+
+ '
'+
+ '
'+
+ '
'+
+ (this.showSeconds ?
+ '
'+
+ '
'
+ : '') +
+ (this.showMeridian ?
+ '
'+
+ '
'
+ : '') +
+ '
'+
+ '
'+
+ '
'+ hourTemplate +'
'+
+ '
:
'+
+ '
'+ minuteTemplate +'
'+
+ (this.showSeconds ?
+ '
:
'+
+ '
'+ secondTemplate +'
'
+ : '') +
+ (this.showMeridian ?
+ '
'+
+ '
'+ meridianTemplate +'
'
+ : '') +
+ '
'+
+ '
'+
+ '
'+
+ '
'+
+ '
'+
+ (this.showSeconds ?
+ '
'+
+ '
'
+ : '') +
+ (this.showMeridian ?
+ '
'+
+ '
'
+ : '') +
+ '
'+
+ '
';
+
+ var template;
+ switch(this.options.template) {
+ case 'modal':
+ template = '
',minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))};var n=e.fn.affix;e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e.fn.affix.noConflict=function(){return e.fn.affix=n,this},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);
\ No newline at end of file
diff --git a/mall-master/src/main/resources/static/js/breakpoints.js b/mall-master/src/main/resources/static/js/breakpoints.js
new file mode 100644
index 0000000..2e73a35
--- /dev/null
+++ b/mall-master/src/main/resources/static/js/breakpoints.js
@@ -0,0 +1,90 @@
+/*
+ Breakpoints.js
+ version 1.0
+
+ Creates handy events for your responsive design breakpoints
+
+ Copyright 2011 XOXCO, Inc
+ http://xoxco.com/
+
+ Documentation for this plugin lives here:
+ http://xoxco.com/projects/code/breakpoints
+
+ Licensed under the MIT license:
+ http://www.opensource.org/licenses/mit-license.php
+
+*/
+(function($) {
+
+ var lastSize = 0;
+ var interval = null;
+
+ $.fn.resetBreakpoints = function() {
+ $(window).unbind('resize');
+ if (interval) {
+ clearInterval(interval);
+ }
+ lastSize = 0;
+ };
+
+ $.fn.setBreakpoints = function(settings) {
+ var options = jQuery.extend({
+ distinct: true,
+ breakpoints: new Array(320,480,768,1024)
+ },settings);
+
+
+ interval = setInterval(function() {
+
+ var w = $(window).width();
+ var done = false;
+
+ for (var bp in options.breakpoints.sort(function(a,b) { return (b-a) })) {
+
+ // fire onEnter when a browser expands into a new breakpoint
+ // if in distinct mode, remove all other breakpoints first.
+ if (!done && w >= options.breakpoints[bp] && lastSize < options.breakpoints[bp]) {
+ if (options.distinct) {
+ for (var x in options.breakpoints.sort(function(a,b) { return (b-a) })) {
+ if ($('body').hasClass('breakpoint-' + options.breakpoints[x])) {
+ $('body').removeClass('breakpoint-' + options.breakpoints[x]);
+ $(window).trigger('exitBreakpoint' + options.breakpoints[x]);
+ }
+ }
+ done = true;
+ }
+ $('body').addClass('breakpoint-' + options.breakpoints[bp]);
+ $(window).trigger('enterBreakpoint' + options.breakpoints[bp]);
+
+ }
+
+ // fire onExit when browser contracts out of a larger breakpoint
+ if (w < options.breakpoints[bp] && lastSize >= options.breakpoints[bp]) {
+ $('body').removeClass('breakpoint-' + options.breakpoints[bp]);
+ $(window).trigger('exitBreakpoint' + options.breakpoints[bp]);
+
+ }
+
+ // if in distinct mode, fire onEnter when browser contracts into a smaller breakpoint
+ if (
+ options.distinct && // only one breakpoint at a time
+ w >= options.breakpoints[bp] && // and we are in this one
+ w < options.breakpoints[bp-1] && // and smaller than the bigger one
+ lastSize > w && // and we contracted
+ lastSize >0 && // and this is not the first time
+ !$('body').hasClass('breakpoint-' + options.breakpoints[bp]) // and we aren't already in this breakpoint
+ ) {
+ $('body').addClass('breakpoint-' + options.breakpoints[bp]);
+ $(window).trigger('enterBreakpoint' + options.breakpoints[bp]);
+
+ }
+ }
+
+ // set up for next call
+ if (lastSize != w) {
+ lastSize = w;
+ }
+ },250);
+ };
+
+})(jQuery);
diff --git a/mall-master/src/main/resources/static/js/breakpoints.min.js b/mall-master/src/main/resources/static/js/breakpoints.min.js
new file mode 100644
index 0000000..ec48aa9
--- /dev/null
+++ b/mall-master/src/main/resources/static/js/breakpoints.min.js
@@ -0,0 +1 @@
+(function(c){var b=0;var a=null;c.fn.resetBreakpoints=function(){c(window).unbind("resize");if(a){clearInterval(a)}b=0};c.fn.setBreakpoints=function(e){var d=jQuery.extend({distinct:true,breakpoints:new Array(320,480,768,1024)},e);a=setInterval(function(){var h=c(window).width();var g=false;for(var i in d.breakpoints.sort(function(k,j){return(j-k)})){if(!g&&h>=d.breakpoints[i]&&b=d.breakpoints[i]){c("body").removeClass("breakpoint-"+d.breakpoints[i]);c(window).trigger("exitBreakpoint"+d.breakpoints[i])}if(d.distinct&&h>=d.breakpoints[i]&&hh&&b>0&&!c("body").hasClass("breakpoint-"+d.breakpoints[i])){c("body").addClass("breakpoint-"+d.breakpoints[i]);c(window).trigger("enterBreakpoint"+d.breakpoints[i])}}if(b!=h){b=h}},250)}})(jQuery);
\ No newline at end of file
diff --git a/mall-master/src/main/resources/static/js/calendar.js b/mall-master/src/main/resources/static/js/calendar.js
new file mode 100644
index 0000000..1085530
--- /dev/null
+++ b/mall-master/src/main/resources/static/js/calendar.js
@@ -0,0 +1,185 @@
+var Calendar = function () {
+
+
+ return {
+ //main function to initiate the module
+ init: function () {
+
+ App.addResponsiveHandler(function () {
+ Calendar.initCalendar();
+ });
+
+ $('.page-sidebar .sidebar-toggler').click(function () {
+ Calendar.initCalendar();
+ });
+
+ Calendar.initCalendar();
+ },
+
+ initCalendar: function () {
+
+ if (!jQuery().fullCalendar) {
+ return;
+ }
+
+ var date = new Date();
+ var d = date.getDate();
+ var m = date.getMonth();
+ var y = date.getFullYear();
+
+ var h = {};
+
+ if (App.isRTL()) {
+ if ($('#calendar').parents(".portlet").width() <= 720) {
+ $('#calendar').addClass("mobile");
+ h = {
+ right: 'title, prev, next',
+ center: '',
+ right: 'agendaDay, agendaWeek, month, today'
+ };
+ } else {
+ $('#calendar').removeClass("mobile");
+ h = {
+ right: 'title',
+ center: '',
+ left: 'agendaDay, agendaWeek, month, today, prev,next'
+ };
+ }
+ } else {
+ if ($('#calendar').parents(".portlet").width() <= 720) {
+ $('#calendar').addClass("mobile");
+ h = {
+ left: 'title, prev, next',
+ center: '',
+ right: 'today,month,agendaWeek,agendaDay'
+ };
+ } else {
+ $('#calendar').removeClass("mobile");
+ h = {
+ left: 'title',
+ center: '',
+ right: 'prev,next,today,month,agendaWeek,agendaDay'
+ };
+ }
+ }
+
+
+ var initDrag = function (el) {
+ // create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)
+ // it doesn't need to have a start or end
+ var eventObject = {
+ title: $.trim(el.text()) // use the element's text as the event title
+ };
+ // store the Event Object in the DOM element so we can get to it later
+ el.data('eventObject', eventObject);
+ // make the event draggable using jQuery UI
+ el.draggable({
+ zIndex: 999,
+ revert: true, // will cause the event to go back to its
+ revertDuration: 0 // original position after the drag
+ });
+ }
+
+ var addEvent = function (title) {
+ title = title.length == 0 ? "Untitled Event" : title;
+ var html = $('
' + title + '
');
+ jQuery('#event_box').append(html);
+ initDrag(html);
+ }
+
+ $('#external-events div.external-event').each(function () {
+ initDrag($(this))
+ });
+
+ $('#event_add').unbind('click').click(function () {
+ var title = $('#event_title').val();
+ addEvent(title);
+ });
+
+ //predefined events
+ $('#event_box').html("");
+ addEvent("My Event 1");
+ addEvent("My Event 2");
+ addEvent("My Event 3");
+ addEvent("My Event 4");
+ addEvent("My Event 5");
+ addEvent("My Event 6");
+
+ $('#calendar').fullCalendar('destroy'); // destroy the calendar
+ $('#calendar').fullCalendar({ //re-initialize the calendar
+ header: h,
+ slotMinutes: 15,
+ editable: true,
+ droppable: true, // this allows things to be dropped onto the calendar !!!
+ drop: function (date, allDay) { // this function is called when something is dropped
+
+ // retrieve the dropped element's stored Event Object
+ var originalEventObject = $(this).data('eventObject');
+ // we need to copy it, so that multiple events don't have a reference to the same object
+ var copiedEventObject = $.extend({}, originalEventObject);
+
+ // assign it the date that was reported
+ copiedEventObject.start = date;
+ copiedEventObject.allDay = allDay;
+ copiedEventObject.className = $(this).attr("data-class");
+
+ // render the event on the calendar
+ // the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
+ $('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
+
+ // is the "remove after drop" checkbox checked?
+ if ($('#drop-remove').is(':checked')) {
+ // if so, remove the element from the "Draggable Events" list
+ $(this).remove();
+ }
+ },
+ events: [{
+ title: 'All Day Event',
+ start: new Date(y, m, 1),
+ backgroundColor: App.getLayoutColorCode('yellow')
+ }, {
+ title: 'Long Event',
+ start: new Date(y, m, d - 5),
+ end: new Date(y, m, d - 2),
+ backgroundColor: App.getLayoutColorCode('green')
+ }, {
+ title: 'Repeating Event',
+ start: new Date(y, m, d - 3, 16, 0),
+ allDay: false,
+ backgroundColor: App.getLayoutColorCode('red')
+ }, {
+ title: 'Repeating Event',
+ start: new Date(y, m, d + 4, 16, 0),
+ allDay: false,
+ backgroundColor: App.getLayoutColorCode('green')
+ }, {
+ title: 'Meeting',
+ start: new Date(y, m, d, 10, 30),
+ allDay: false,
+ }, {
+ title: 'Lunch',
+ start: new Date(y, m, d, 12, 0),
+ end: new Date(y, m, d, 14, 0),
+ backgroundColor: App.getLayoutColorCode('grey'),
+ allDay: false,
+ }, {
+ title: 'Birthday Party',
+ start: new Date(y, m, d + 1, 19, 0),
+ end: new Date(y, m, d + 1, 22, 30),
+ backgroundColor: App.getLayoutColorCode('purple'),
+ allDay: false,
+ }, {
+ title: 'Click for Google',
+ start: new Date(y, m, 28),
+ end: new Date(y, m, 29),
+ backgroundColor: App.getLayoutColorCode('yellow'),
+ url: 'http://google.com/',
+ }
+ ]
+ });
+
+ }
+
+ };
+
+}();
\ No newline at end of file
diff --git a/mall-master/src/main/resources/static/js/canvas-to-blob.min.js b/mall-master/src/main/resources/static/js/canvas-to-blob.min.js
new file mode 100644
index 0000000..d6bb8ca
--- /dev/null
+++ b/mall-master/src/main/resources/static/js/canvas-to-blob.min.js
@@ -0,0 +1 @@
+(function(a){"use strict";var b=a.HTMLCanvasElement&&a.HTMLCanvasElement.prototype,c=a.Blob&&function(){try{return Boolean(new Blob)}catch(a){return!1}}(),d=c&&a.Uint8Array&&function(){try{return(new Blob([new Uint8Array(100)])).size===100}catch(a){return!1}}(),e=a.BlobBuilder||a.WebKitBlobBuilder||a.MozBlobBuilder||a.MSBlobBuilder,f=(c||e)&&a.atob&&a.ArrayBuffer&&a.Uint8Array&&function(a){var b,f,g,h,i,j;a.split(",")[0].indexOf("base64")>=0?b=atob(a.split(",")[1]):b=decodeURIComponent(a.split(",")[1]),f=new ArrayBuffer(b.length),g=new Uint8Array(f);for(h=0;h 0) data = data.slice(1);
+ // do a random walk
+ while (data.length < totalPoints) {
+ var prev = data.length > 0 ? data[data.length - 1] : 50;
+ var y = prev + Math.random() * 10 - 5;
+ if (y < 0) y = 0;
+ if (y > 100) y = 100;
+ data.push(y);
+ }
+ // zip the generated y values with the x values
+ var res = [];
+ for (var i = 0; i < data.length; ++i) res.push([i, data[i]])
+ return res;
+ }
+
+ //Basic Chart
+
+ function chart1() {
+ var d1 = [];
+ for (var i = 0; i < Math.PI * 2; i += 0.25)
+ d1.push([i, Math.sin(i)]);
+
+ var d2 = [];
+ for (var i = 0; i < Math.PI * 2; i += 0.25)
+ d2.push([i, Math.cos(i)]);
+
+ var d3 = [];
+ for (var i = 0; i < Math.PI * 2; i += 0.1)
+ d3.push([i, Math.tan(i)]);
+
+ $.plot($("#chart_1"), [{
+ label: "sin(x)",
+ data: d1
+ }, {
+ label: "cos(x)",
+ data: d2
+ }, {
+ label: "tan(x)",
+ data: d3
+ }
+ ], {
+ series: {
+ lines: {
+ show: true
+ },
+ points: {
+ show: true
+ }
+ },
+ xaxis: {
+ ticks: [0, [Math.PI / 2, "\u03c0/2"],
+ [Math.PI, "\u03c0"],
+ [Math.PI * 3 / 2, "3\u03c0/2"],
+ [Math.PI * 2, "2\u03c0"]
+ ]
+ },
+ yaxis: {
+ ticks: 10,
+ min: -2,
+ max: 2
+ },
+ grid: {
+ backgroundColor: {
+ colors: ["#fff", "#eee"]
+ }
+ }
+ });
+
+ }
+
+ //Interactive Chart
+
+ function chart2() {
+ function randValue() {
+ return (Math.floor(Math.random() * (1 + 40 - 20))) + 20;
+ }
+ var pageviews = [
+ [1, randValue()],
+ [2, randValue()],
+ [3, 2 + randValue()],
+ [4, 3 + randValue()],
+ [5, 5 + randValue()],
+ [6, 10 + randValue()],
+ [7, 15 + randValue()],
+ [8, 20 + randValue()],
+ [9, 25 + randValue()],
+ [10, 30 + randValue()],
+ [11, 35 + randValue()],
+ [12, 25 + randValue()],
+ [13, 15 + randValue()],
+ [14, 20 + randValue()],
+ [15, 45 + randValue()],
+ [16, 50 + randValue()],
+ [17, 65 + randValue()],
+ [18, 70 + randValue()],
+ [19, 85 + randValue()],
+ [20, 80 + randValue()],
+ [21, 75 + randValue()],
+ [22, 80 + randValue()],
+ [23, 75 + randValue()],
+ [24, 70 + randValue()],
+ [25, 65 + randValue()],
+ [26, 75 + randValue()],
+ [27, 80 + randValue()],
+ [28, 85 + randValue()],
+ [29, 90 + randValue()],
+ [30, 95 + randValue()]
+ ];
+ var visitors = [
+ [1, randValue() - 5],
+ [2, randValue() - 5],
+ [3, randValue() - 5],
+ [4, 6 + randValue()],
+ [5, 5 + randValue()],
+ [6, 20 + randValue()],
+ [7, 25 + randValue()],
+ [8, 36 + randValue()],
+ [9, 26 + randValue()],
+ [10, 38 + randValue()],
+ [11, 39 + randValue()],
+ [12, 50 + randValue()],
+ [13, 51 + randValue()],
+ [14, 12 + randValue()],
+ [15, 13 + randValue()],
+ [16, 14 + randValue()],
+ [17, 15 + randValue()],
+ [18, 15 + randValue()],
+ [19, 16 + randValue()],
+ [20, 17 + randValue()],
+ [21, 18 + randValue()],
+ [22, 19 + randValue()],
+ [23, 20 + randValue()],
+ [24, 21 + randValue()],
+ [25, 14 + randValue()],
+ [26, 24 + randValue()],
+ [27, 25 + randValue()],
+ [28, 26 + randValue()],
+ [29, 27 + randValue()],
+ [30, 31 + randValue()]
+ ];
+
+ var plot = $.plot($("#chart_2"), [{
+ data: pageviews,
+ label: "Unique Visits"
+ }, {
+ data: visitors,
+ label: "Page Views"
+ }
+ ], {
+ series: {
+ lines: {
+ show: true,
+ lineWidth: 2,
+ fill: true,
+ fillColor: {
+ colors: [{
+ opacity: 0.05
+ }, {
+ opacity: 0.01
+ }
+ ]
+ }
+ },
+ points: {
+ show: true
+ },
+ shadowSize: 2
+ },
+ grid: {
+ hoverable: true,
+ clickable: true,
+ tickColor: "#eee",
+ borderWidth: 0
+ },
+ colors: ["#d12610", "#37b7f3", "#52e136"],
+ xaxis: {
+ ticks: 11,
+ tickDecimals: 0
+ },
+ yaxis: {
+ ticks: 11,
+ tickDecimals: 0
+ }
+ });
+
+
+ function showTooltip(x, y, contents) {
+ $('
+ */
+wysihtml5.dom.convertToList = (function() {
+ function _createListItem(doc, list) {
+ var listItem = doc.createElement("li");
+ list.appendChild(listItem);
+ return listItem;
+ }
+
+ function _createList(doc, type) {
+ return doc.createElement(type);
+ }
+
+ function convertToList(element, listType) {
+ if (element.nodeName === "UL" || element.nodeName === "OL" || element.nodeName === "MENU") {
+ // Already a list
+ return element;
+ }
+
+ var doc = element.ownerDocument,
+ list = _createList(doc, listType),
+ lineBreaks = element.querySelectorAll("br"),
+ lineBreaksLength = lineBreaks.length,
+ childNodes,
+ childNodesLength,
+ childNode,
+ lineBreak,
+ parentNode,
+ isBlockElement,
+ isLineBreak,
+ currentListItem,
+ i;
+
+ // First find at the end of inline elements and move them behind them
+ for (i=0; i if empty, otherwise create a new one
+ currentListItem = currentListItem.firstChild ? _createListItem(doc, list) : currentListItem;
+ currentListItem.appendChild(childNode);
+ currentListItem = null;
+ continue;
+ }
+
+ if (isLineBreak) {
+ // Only create a new list item in the next iteration when the current one has already content
+ currentListItem = currentListItem.firstChild ? null : currentListItem;
+ continue;
+ }
+
+ currentListItem.appendChild(childNode);
+ }
+
+ element.parentNode.replaceChild(list, element);
+ return list;
+ }
+
+ return convertToList;
+})();/**
+ * Copy a set of attributes from one element to another
+ *
+ * @param {Array} attributesToCopy List of attributes which should be copied
+ * @return {Object} Returns an object which offers the "from" method which can be invoked with the element where to
+ * copy the attributes from., this again returns an object which provides a method named "to" which can be invoked
+ * with the element where to copy the attributes to (see example)
+ *
+ * @example
+ * var textarea = document.querySelector("textarea"),
+ * div = document.querySelector("div[contenteditable=true]"),
+ * anotherDiv = document.querySelector("div.preview");
+ * wysihtml5.dom.copyAttributes(["spellcheck", "value", "placeholder"]).from(textarea).to(div).andTo(anotherDiv);
+ *
+ */
+wysihtml5.dom.copyAttributes = function(attributesToCopy) {
+ return {
+ from: function(elementToCopyFrom) {
+ return {
+ to: function(elementToCopyTo) {
+ var attribute,
+ i = 0,
+ length = attributesToCopy.length;
+ for (; ifoo");
+ */
+wysihtml5.dom.getAsDom = (function() {
+
+ var _innerHTMLShiv = function(html, context) {
+ var tempElement = context.createElement("div");
+ tempElement.style.display = "none";
+ context.body.appendChild(tempElement);
+ // IE throws an exception when trying to insert via innerHTML
+ try { tempElement.innerHTML = html; } catch(e) {}
+ context.body.removeChild(tempElement);
+ return tempElement;
+ };
+
+ /**
+ * Make sure IE supports HTML5 tags, which is accomplished by simply creating one instance of each element
+ */
+ var _ensureHTML5Compatibility = function(context) {
+ if (context._wysihtml5_supportsHTML5Tags) {
+ return;
+ }
+ for (var i=0, length=HTML5_ELEMENTS.length; i "block"
+ */
+wysihtml5.dom.getStyle = (function() {
+ var stylePropertyMapping = {
+ "float": ("styleFloat" in document.createElement("div").style) ? "styleFloat" : "cssFloat"
+ },
+ REG_EXP_CAMELIZE = /\-[a-z]/g;
+
+ function camelize(str) {
+ return str.replace(REG_EXP_CAMELIZE, function(match) {
+ return match.charAt(1).toUpperCase();
+ });
+ }
+
+ return function(property) {
+ return {
+ from: function(element) {
+ if (element.nodeType !== wysihtml5.ELEMENT_NODE) {
+ return;
+ }
+
+ var doc = element.ownerDocument,
+ camelizedProperty = stylePropertyMapping[property] || camelize(property),
+ style = element.style,
+ currentStyle = element.currentStyle,
+ styleValue = style[camelizedProperty];
+ if (styleValue) {
+ return styleValue;
+ }
+
+ // currentStyle is no standard and only supported by Opera and IE but it has one important advantage over the standard-compliant
+ // window.getComputedStyle, since it returns css property values in their original unit:
+ // If you set an elements width to "50%", window.getComputedStyle will give you it's current width in px while currentStyle
+ // gives you the original "50%".
+ // Opera supports both, currentStyle and window.getComputedStyle, that's why checking for currentStyle should have higher prio
+ if (currentStyle) {
+ try {
+ return currentStyle[camelizedProperty];
+ } catch(e) {
+ //ie will occasionally fail for unknown reasons. swallowing exception
+ }
+ }
+
+ var win = doc.defaultView || doc.parentWindow,
+ needsOverflowReset = (property === "height" || property === "width") && element.nodeName === "TEXTAREA",
+ originalOverflow,
+ returnValue;
+
+ if (win.getComputedStyle) {
+ // Chrome and Safari both calculate a wrong width and height for textareas when they have scroll bars
+ // therfore we remove and restore the scrollbar and calculate the value in between
+ if (needsOverflowReset) {
+ originalOverflow = style.overflow;
+ style.overflow = "hidden";
+ }
+ returnValue = win.getComputedStyle(element, null).getPropertyValue(property);
+ if (needsOverflowReset) {
+ style.overflow = originalOverflow || "";
+ }
+ return returnValue;
+ }
+ }
+ };
+ };
+})();/**
+ * High performant way to check whether an element with a specific tag name is in the given document
+ * Optimized for being heavily executed
+ * Unleashes the power of live node lists
+ *
+ * @param {Object} doc The document object of the context where to check
+ * @param {String} tagName Upper cased tag name
+ * @example
+ * wysihtml5.dom.hasElementWithTagName(document, "IMG");
+ */
+wysihtml5.dom.hasElementWithTagName = (function() {
+ var LIVE_CACHE = {},
+ DOCUMENT_IDENTIFIER = 1;
+
+ function _getDocumentIdentifier(doc) {
+ return doc._wysihtml5_identifier || (doc._wysihtml5_identifier = DOCUMENT_IDENTIFIER++);
+ }
+
+ return function(doc, tagName) {
+ var key = _getDocumentIdentifier(doc) + ":" + tagName,
+ cacheEntry = LIVE_CACHE[key];
+ if (!cacheEntry) {
+ cacheEntry = LIVE_CACHE[key] = doc.getElementsByTagName(tagName);
+ }
+
+ return cacheEntry.length > 0;
+ };
+})();/**
+ * High performant way to check whether an element with a specific class name is in the given document
+ * Optimized for being heavily executed
+ * Unleashes the power of live node lists
+ *
+ * @param {Object} doc The document object of the context where to check
+ * @param {String} tagName Upper cased tag name
+ * @example
+ * wysihtml5.dom.hasElementWithClassName(document, "foobar");
+ */
+(function(wysihtml5) {
+ var LIVE_CACHE = {},
+ DOCUMENT_IDENTIFIER = 1;
+
+ function _getDocumentIdentifier(doc) {
+ return doc._wysihtml5_identifier || (doc._wysihtml5_identifier = DOCUMENT_IDENTIFIER++);
+ }
+
+ wysihtml5.dom.hasElementWithClassName = function(doc, className) {
+ // getElementsByClassName is not supported by IE<9
+ // but is sometimes mocked via library code (which then doesn't return live node lists)
+ if (!wysihtml5.browser.supportsNativeGetElementsByClassName()) {
+ return !!doc.querySelector("." + className);
+ }
+
+ var key = _getDocumentIdentifier(doc) + ":" + className,
+ cacheEntry = LIVE_CACHE[key];
+ if (!cacheEntry) {
+ cacheEntry = LIVE_CACHE[key] = doc.getElementsByClassName(className);
+ }
+
+ return cacheEntry.length > 0;
+ };
+})(wysihtml5);
+wysihtml5.dom.insert = function(elementToInsert) {
+ return {
+ after: function(element) {
+ element.parentNode.insertBefore(elementToInsert, element.nextSibling);
+ },
+
+ before: function(element) {
+ element.parentNode.insertBefore(elementToInsert, element);
+ },
+
+ into: function(element) {
+ element.appendChild(elementToInsert);
+ }
+ };
+};wysihtml5.dom.insertCSS = function(rules) {
+ rules = rules.join("\n");
+
+ return {
+ into: function(doc) {
+ var head = doc.head || doc.getElementsByTagName("head")[0],
+ styleElement = doc.createElement("style");
+
+ styleElement.type = "text/css";
+
+ if (styleElement.styleSheet) {
+ styleElement.styleSheet.cssText = rules;
+ } else {
+ styleElement.appendChild(doc.createTextNode(rules));
+ }
+
+ if (head) {
+ head.appendChild(styleElement);
+ }
+ }
+ };
+};/**
+ * Method to set dom events
+ *
+ * @example
+ * wysihtml5.dom.observe(iframe.contentWindow.document.body, ["focus", "blur"], function() { ... });
+ */
+wysihtml5.dom.observe = function(element, eventNames, handler) {
+ eventNames = typeof(eventNames) === "string" ? [eventNames] : eventNames;
+
+ var handlerWrapper,
+ eventName,
+ i = 0,
+ length = eventNames.length;
+
+ for (; i
foo bar
+ *
+ * var userHTML = '
I'm a table!
';
+ * wysihtml5.dom.parse(userHTML);
+ * // => 'I'm a table!'
+ *
+ * var userHTML = '
'
+ */
+wysihtml5.dom.parse = (function() {
+
+ /**
+ * It's not possible to use a XMLParser/DOMParser as HTML5 is not always well-formed XML
+ * new DOMParser().parseFromString('') will cause a parseError since the
+ * node isn't closed
+ *
+ * Therefore we've to use the browser's ordinary HTML parser invoked by setting innerHTML.
+ */
+ var NODE_TYPE_MAPPING = {
+ "1": _handleElement,
+ "3": _handleText
+ },
+ // Rename unknown tags to this
+ DEFAULT_NODE_NAME = "span",
+ WHITE_SPACE_REG_EXP = /\s+/,
+ defaultRules = { tags: {}, classes: {} },
+ currentRules = {};
+
+ /**
+ * Iterates over all childs of the element, recreates them, appends them into a document fragment
+ * which later replaces the entire body content
+ */
+ function parse(elementOrHtml, rules, context, cleanUp) {
+ wysihtml5.lang.object(currentRules).merge(defaultRules).merge(rules).get();
+
+ context = context || elementOrHtml.ownerDocument || document;
+ var fragment = context.createDocumentFragment(),
+ isString = typeof(elementOrHtml) === "string",
+ element,
+ newNode,
+ firstChild;
+
+ if (isString) {
+ element = wysihtml5.dom.getAsDom(elementOrHtml, context);
+ } else {
+ element = elementOrHtml;
+ }
+
+ while (element.firstChild) {
+ firstChild = element.firstChild;
+ element.removeChild(firstChild);
+ newNode = _convert(firstChild, cleanUp);
+ if (newNode) {
+ fragment.appendChild(newNode);
+ }
+ }
+
+ // Clear element contents
+ element.innerHTML = "";
+
+ // Insert new DOM tree
+ element.appendChild(fragment);
+
+ return isString ? wysihtml5.quirks.getCorrectInnerHTML(element) : element;
+ }
+
+ function _convert(oldNode, cleanUp) {
+ var oldNodeType = oldNode.nodeType,
+ oldChilds = oldNode.childNodes,
+ oldChildsLength = oldChilds.length,
+ newNode,
+ method = NODE_TYPE_MAPPING[oldNodeType],
+ i = 0;
+
+ newNode = method && method(oldNode);
+
+ if (!newNode) {
+ return null;
+ }
+
+ for (i=0; i elements
+ if (cleanUp &&
+ newNode.childNodes.length <= 1 &&
+ newNode.nodeName.toLowerCase() === DEFAULT_NODE_NAME &&
+ !newNode.attributes.length) {
+ return newNode.firstChild;
+ }
+
+ return newNode;
+ }
+
+ function _handleElement(oldNode) {
+ var rule,
+ newNode,
+ endTag,
+ tagRules = currentRules.tags,
+ nodeName = oldNode.nodeName.toLowerCase(),
+ scopeName = oldNode.scopeName;
+
+ /**
+ * We already parsed that element
+ * ignore it! (yes, this sometimes happens in IE8 when the html is invalid)
+ */
+ if (oldNode._wysihtml5) {
+ return null;
+ }
+ oldNode._wysihtml5 = 1;
+
+ if (oldNode.className === "wysihtml5-temp") {
+ return null;
+ }
+
+ /**
+ * IE is the only browser who doesn't include the namespace in the
+ * nodeName, that's why we have to prepend it by ourselves
+ * scopeName is a proprietary IE feature
+ * read more here http://msdn.microsoft.com/en-us/library/ms534388(v=vs.85).aspx
+ */
+ if (scopeName && scopeName != "HTML") {
+ nodeName = scopeName + ":" + nodeName;
+ }
+
+ /**
+ * Repair node
+ * IE is a bit bitchy when it comes to invalid nested markup which includes unclosed tags
+ * A
doesn't need to be closed according HTML4-5 spec, we simply replace it with a
to preserve its content and layout
+ */
+ if ("outerHTML" in oldNode) {
+ if (!wysihtml5.browser.autoClosesUnclosedTags() &&
+ oldNode.nodeName === "P" &&
+ oldNode.outerHTML.slice(-4).toLowerCase() !== "") {
+ nodeName = "div";
+ }
+ }
+
+ if (nodeName in tagRules) {
+ rule = tagRules[nodeName];
+ if (!rule || rule.remove) {
+ return null;
+ }
+
+ rule = typeof(rule) === "string" ? { rename_tag: rule } : rule;
+ } else if (oldNode.firstChild) {
+ rule = { rename_tag: DEFAULT_NODE_NAME };
+ } else {
+ // Remove empty unknown elements
+ return null;
+ }
+
+ newNode = oldNode.ownerDocument.createElement(rule.rename_tag || nodeName);
+ _handleAttributes(oldNode, newNode, rule);
+
+ oldNode = null;
+ return newNode;
+ }
+
+ function _handleAttributes(oldNode, newNode, rule) {
+ var attributes = {}, // fresh new set of attributes to set on newNode
+ setClass = rule.set_class, // classes to set
+ addClass = rule.add_class, // add classes based on existing attributes
+ setAttributes = rule.set_attributes, // attributes to set on the current node
+ checkAttributes = rule.check_attributes, // check/convert values of attributes
+ allowedClasses = currentRules.classes,
+ i = 0,
+ classes = [],
+ newClasses = [],
+ newUniqueClasses = [],
+ oldClasses = [],
+ classesLength,
+ newClassesLength,
+ currentClass,
+ newClass,
+ attributeName,
+ newAttributeValue,
+ method;
+
+ if (setAttributes) {
+ attributes = wysihtml5.lang.object(setAttributes).clone();
+ }
+
+ if (checkAttributes) {
+ for (attributeName in checkAttributes) {
+ method = attributeCheckMethods[checkAttributes[attributeName]];
+ if (!method) {
+ continue;
+ }
+ newAttributeValue = method(_getAttribute(oldNode, attributeName));
+ if (typeof(newAttributeValue) === "string") {
+ attributes[attributeName] = newAttributeValue;
+ }
+ }
+ }
+
+ if (setClass) {
+ classes.push(setClass);
+ }
+
+ if (addClass) {
+ for (attributeName in addClass) {
+ method = addClassMethods[addClass[attributeName]];
+ if (!method) {
+ continue;
+ }
+ newClass = method(_getAttribute(oldNode, attributeName));
+ if (typeof(newClass) === "string") {
+ classes.push(newClass);
+ }
+ }
+ }
+
+ // make sure that wysihtml5 temp class doesn't get stripped out
+ allowedClasses["_wysihtml5-temp-placeholder"] = 1;
+
+ // add old classes last
+ oldClasses = oldNode.getAttribute("class");
+ if (oldClasses) {
+ classes = classes.concat(oldClasses.split(WHITE_SPACE_REG_EXP));
+ }
+ classesLength = classes.length;
+ for (; i under https when it's new attribute value is non-https
+ // TODO: Investigate this further and check for smarter handling
+ try {
+ newNode.setAttribute(attributeName, attributes[attributeName]);
+ } catch(e) {}
+ }
+
+ // IE8 sometimes loses the width/height attributes when those are set before the "src"
+ // so we make sure to set them again
+ if (attributes.src) {
+ if (typeof(attributes.width) !== "undefined") {
+ newNode.setAttribute("width", attributes.width);
+ }
+ if (typeof(attributes.height) !== "undefined") {
+ newNode.setAttribute("height", attributes.height);
+ }
+ }
+ }
+
+ /**
+ * IE gives wrong results for hasAttribute/getAttribute, for example:
+ * var td = document.createElement("td");
+ * td.getAttribute("rowspan"); // => "1" in IE
+ *
+ * Therefore we have to check the element's outerHTML for the attribute
+ */
+ var HAS_GET_ATTRIBUTE_BUG = !wysihtml5.browser.supportsGetAttributeCorrectly();
+ function _getAttribute(node, attributeName) {
+ attributeName = attributeName.toLowerCase();
+ var nodeName = node.nodeName;
+ if (nodeName == "IMG" && attributeName == "src" && _isLoadedImage(node) === true) {
+ // Get 'src' attribute value via object property since this will always contain the
+ // full absolute url (http://...)
+ // this fixes a very annoying bug in firefox (ver 3.6 & 4) and IE 8 where images copied from the same host
+ // will have relative paths, which the sanitizer strips out (see attributeCheckMethods.url)
+ return node.src;
+ } else if (HAS_GET_ATTRIBUTE_BUG && "outerHTML" in node) {
+ // Don't trust getAttribute/hasAttribute in IE 6-8, instead check the element's outerHTML
+ var outerHTML = node.outerHTML.toLowerCase(),
+ // TODO: This might not work for attributes without value:
+ hasAttribute = outerHTML.indexOf(" " + attributeName + "=") != -1;
+
+ return hasAttribute ? node.getAttribute(attributeName) : null;
+ } else{
+ return node.getAttribute(attributeName);
+ }
+ }
+
+ /**
+ * Check whether the given node is a proper loaded image
+ * FIXME: Returns undefined when unknown (Chrome, Safari)
+ */
+ function _isLoadedImage(node) {
+ try {
+ return node.complete && !node.mozMatchesSelector(":-moz-broken");
+ } catch(e) {
+ if (node.complete && node.readyState === "complete") {
+ return true;
+ }
+ }
+ }
+
+ function _handleText(oldNode) {
+ return oldNode.ownerDocument.createTextNode(oldNode.data);
+ }
+
+
+ // ------------ attribute checks ------------ \\
+ var attributeCheckMethods = {
+ url: (function() {
+ var REG_EXP = /^https?:\/\//i;
+ return function(attributeValue) {
+ if (!attributeValue || !attributeValue.match(REG_EXP)) {
+ return null;
+ }
+ return attributeValue.replace(REG_EXP, function(match) {
+ return match.toLowerCase();
+ });
+ };
+ })(),
+
+ alt: (function() {
+ var REG_EXP = /[^ a-z0-9_\-]/gi;
+ return function(attributeValue) {
+ if (!attributeValue) {
+ return "";
+ }
+ return attributeValue.replace(REG_EXP, "");
+ };
+ })(),
+
+ numbers: (function() {
+ var REG_EXP = /\D/g;
+ return function(attributeValue) {
+ attributeValue = (attributeValue || "").replace(REG_EXP, "");
+ return attributeValue || null;
+ };
+ })()
+ };
+
+ // ------------ class converter (converts an html attribute to a class name) ------------ \\
+ var addClassMethods = {
+ align_img: (function() {
+ var mapping = {
+ left: "wysiwyg-float-left",
+ right: "wysiwyg-float-right"
+ };
+ return function(attributeValue) {
+ return mapping[String(attributeValue).toLowerCase()];
+ };
+ })(),
+
+ align_text: (function() {
+ var mapping = {
+ left: "wysiwyg-text-align-left",
+ right: "wysiwyg-text-align-right",
+ center: "wysiwyg-text-align-center",
+ justify: "wysiwyg-text-align-justify"
+ };
+ return function(attributeValue) {
+ return mapping[String(attributeValue).toLowerCase()];
+ };
+ })(),
+
+ clear_br: (function() {
+ var mapping = {
+ left: "wysiwyg-clear-left",
+ right: "wysiwyg-clear-right",
+ both: "wysiwyg-clear-both",
+ all: "wysiwyg-clear-both"
+ };
+ return function(attributeValue) {
+ return mapping[String(attributeValue).toLowerCase()];
+ };
+ })(),
+
+ size_font: (function() {
+ var mapping = {
+ "1": "wysiwyg-font-size-xx-small",
+ "2": "wysiwyg-font-size-small",
+ "3": "wysiwyg-font-size-medium",
+ "4": "wysiwyg-font-size-large",
+ "5": "wysiwyg-font-size-x-large",
+ "6": "wysiwyg-font-size-xx-large",
+ "7": "wysiwyg-font-size-xx-large",
+ "-": "wysiwyg-font-size-smaller",
+ "+": "wysiwyg-font-size-larger"
+ };
+ return function(attributeValue) {
+ return mapping[String(attributeValue).charAt(0)];
+ };
+ })()
+ };
+
+ return parse;
+})();/**
+ * Checks for empty text node childs and removes them
+ *
+ * @param {Element} node The element in which to cleanup
+ * @example
+ * wysihtml5.dom.removeEmptyTextNodes(element);
+ */
+wysihtml5.dom.removeEmptyTextNodes = function(node) {
+ var childNode,
+ childNodes = wysihtml5.lang.array(node.childNodes).get(),
+ childNodesLength = childNodes.length,
+ i = 0;
+ for (; i to a
) and keeps its childs
+ *
+ * @param {Element} element The list element which should be renamed
+ * @param {Element} newNodeName The desired tag name
+ *
+ * @example
+ *
+ *
+ *
eminem
+ *
dr. dre
+ *
50 Cent
+ *
+ *
+ *
+ *
+ *
+ *
+ *
eminem
+ *
dr. dre
+ *
50 Cent
+ *
+ */
+wysihtml5.dom.renameElement = function(element, newNodeName) {
+ var newElement = element.ownerDocument.createElement(newNodeName),
+ firstChild;
+ while (firstChild = element.firstChild) {
+ newElement.appendChild(firstChild);
+ }
+ wysihtml5.dom.copyAttributes(["align", "className"]).from(element).to(newElement);
+ element.parentNode.replaceChild(newElement, element);
+ return newElement;
+};/**
+ * Takes an element, removes it and replaces it with it's childs
+ *
+ * @param {Object} node The node which to replace with it's child nodes
+ * @example
+ *
+ * hello
+ *
+ *
+ */
+wysihtml5.dom.replaceWithChildNodes = function(node) {
+ if (!node.parentNode) {
+ return;
+ }
+
+ if (!node.firstChild) {
+ node.parentNode.removeChild(node);
+ return;
+ }
+
+ var fragment = node.ownerDocument.createDocumentFragment();
+ while (node.firstChild) {
+ fragment.appendChild(node.firstChild);
+ }
+ node.parentNode.replaceChild(fragment, node);
+ node = fragment = null;
+};
+/**
+ * Unwraps an unordered/ordered list
+ *
+ * @param {Element} element The list element which should be unwrapped
+ *
+ * @example
+ *
+ *
+ *
eminem
+ *
dr. dre
+ *
50 Cent
+ *
+ *
+ *
+ *
+ *
+ * eminem
+ * dr. dre
+ * 50 Cent
+ */
+(function(dom) {
+ function _isBlockElement(node) {
+ return dom.getStyle("display").from(node) === "block";
+ }
+
+ function _isLineBreak(node) {
+ return node.nodeName === "BR";
+ }
+
+ function _appendLineBreak(element) {
+ var lineBreak = element.ownerDocument.createElement("br");
+ element.appendChild(lineBreak);
+ }
+
+ function resolveList(list) {
+ if (list.nodeName !== "MENU" && list.nodeName !== "UL" && list.nodeName !== "OL") {
+ return;
+ }
+
+ var doc = list.ownerDocument,
+ fragment = doc.createDocumentFragment(),
+ previousSibling = list.previousElementSibling || list.previousSibling,
+ firstChild,
+ lastChild,
+ isLastChild,
+ shouldAppendLineBreak,
+ listItem;
+
+ if (previousSibling && !_isBlockElement(previousSibling)) {
+ _appendLineBreak(fragment);
+ }
+
+ while (listItem = list.firstChild) {
+ lastChild = listItem.lastChild;
+ while (firstChild = listItem.firstChild) {
+ isLastChild = firstChild === lastChild;
+ // This needs to be done before appending it to the fragment, as it otherwise will loose style information
+ shouldAppendLineBreak = isLastChild && !_isBlockElement(firstChild) && !_isLineBreak(firstChild);
+ fragment.appendChild(firstChild);
+ if (shouldAppendLineBreak) {
+ _appendLineBreak(fragment);
+ }
+ }
+
+ listItem.parentNode.removeChild(listItem);
+ }
+ list.parentNode.replaceChild(fragment, list);
+ }
+
+ dom.resolveList = resolveList;
+})(wysihtml5.dom);/**
+ * Sandbox for executing javascript, parsing css styles and doing dom operations in a secure way
+ *
+ * Browser Compatibility:
+ * - Secure in MSIE 6+, but only when the user hasn't made changes to his security level "restricted"
+ * - Partially secure in other browsers (Firefox, Opera, Safari, Chrome, ...)
+ *
+ * Please note that this class can't benefit from the HTML5 sandbox attribute for the following reasons:
+ * - sandboxing doesn't work correctly with inlined content (src="javascript:'...'")
+ * - sandboxing of physical documents causes that the dom isn't accessible anymore from the outside (iframe.contentWindow, ...)
+ * - setting the "allow-same-origin" flag would fix that, but then still javascript and dom events refuse to fire
+ * - therefore the "allow-scripts" flag is needed, which then would deactivate any security, as the js executed inside the iframe
+ * can do anything as if the sandbox attribute wasn't set
+ *
+ * @param {Function} [readyCallback] Method that gets invoked when the sandbox is ready
+ * @param {Object} [config] Optional parameters
+ *
+ * @example
+ * new wysihtml5.dom.Sandbox(function(sandbox) {
+ * sandbox.getWindow().document.body.innerHTML = '';
+ * });
+ */
+(function(wysihtml5) {
+ var /**
+ * Default configuration
+ */
+ doc = document,
+ /**
+ * Properties to unset/protect on the window object
+ */
+ windowProperties = [
+ "parent", "top", "opener", "frameElement", "frames",
+ "localStorage", "globalStorage", "sessionStorage", "indexedDB"
+ ],
+ /**
+ * Properties on the window object which are set to an empty function
+ */
+ windowProperties2 = [
+ "open", "close", "openDialog", "showModalDialog",
+ "alert", "confirm", "prompt",
+ "openDatabase", "postMessage",
+ "XMLHttpRequest", "XDomainRequest"
+ ],
+ /**
+ * Properties to unset/protect on the document object
+ */
+ documentProperties = [
+ "referrer",
+ "write", "open", "close"
+ ];
+
+ wysihtml5.dom.Sandbox = Base.extend(
+ /** @scope wysihtml5.dom.Sandbox.prototype */ {
+
+ constructor: function(readyCallback, config) {
+ this.callback = readyCallback || wysihtml5.EMPTY_FUNCTION;
+ this.config = wysihtml5.lang.object({}).merge(config).get();
+ this.iframe = this._createIframe();
+ },
+
+ insertInto: function(element) {
+ if (typeof(element) === "string") {
+ element = doc.getElementById(element);
+ }
+
+ element.appendChild(this.iframe);
+ },
+
+ getIframe: function() {
+ return this.iframe;
+ },
+
+ getWindow: function() {
+ this._readyError();
+ },
+
+ getDocument: function() {
+ this._readyError();
+ },
+
+ destroy: function() {
+ var iframe = this.getIframe();
+ iframe.parentNode.removeChild(iframe);
+ },
+
+ _readyError: function() {
+ throw new Error("wysihtml5.Sandbox: Sandbox iframe isn't loaded yet");
+ },
+
+ /**
+ * Creates the sandbox iframe
+ *
+ * Some important notes:
+ * - We can't use HTML5 sandbox for now:
+ * setting it causes that the iframe's dom can't be accessed from the outside
+ * Therefore we need to set the "allow-same-origin" flag which enables accessing the iframe's dom
+ * But then there's another problem, DOM events (focus, blur, change, keypress, ...) aren't fired.
+ * In order to make this happen we need to set the "allow-scripts" flag.
+ * A combination of allow-scripts and allow-same-origin is almost the same as setting no sandbox attribute at all.
+ * - Chrome & Safari, doesn't seem to support sandboxing correctly when the iframe's html is inlined (no physical document)
+ * - IE needs to have the security="restricted" attribute set before the iframe is
+ * inserted into the dom tree
+ * - Believe it or not but in IE "security" in document.createElement("iframe") is false, even
+ * though it supports it
+ * - When an iframe has security="restricted", in IE eval() & execScript() don't work anymore
+ * - IE doesn't fire the onload event when the content is inlined in the src attribute, therefore we rely
+ * on the onreadystatechange event
+ */
+ _createIframe: function() {
+ var that = this,
+ iframe = doc.createElement("iframe");
+ iframe.className = "wysihtml5-sandbox";
+ wysihtml5.dom.setAttributes({
+ "security": "restricted",
+ "allowtransparency": "true",
+ "frameborder": 0,
+ "width": 0,
+ "height": 0,
+ "marginwidth": 0,
+ "marginheight": 0
+ }).on(iframe);
+
+ // Setting the src like this prevents ssl warnings in IE6
+ if (wysihtml5.browser.throwsMixedContentWarningWhenIframeSrcIsEmpty()) {
+ iframe.src = "javascript:''";
+ }
+
+ iframe.onload = function() {
+ iframe.onreadystatechange = iframe.onload = null;
+ that._onLoadIframe(iframe);
+ };
+
+ iframe.onreadystatechange = function() {
+ if (/loaded|complete/.test(iframe.readyState)) {
+ iframe.onreadystatechange = iframe.onload = null;
+ that._onLoadIframe(iframe);
+ }
+ };
+
+ return iframe;
+ },
+
+ /**
+ * Callback for when the iframe has finished loading
+ */
+ _onLoadIframe: function(iframe) {
+ // don't resume when the iframe got unloaded (eg. by removing it from the dom)
+ if (!wysihtml5.dom.contains(doc.documentElement, iframe)) {
+ return;
+ }
+
+ var that = this,
+ iframeWindow = iframe.contentWindow,
+ iframeDocument = iframe.contentWindow.document,
+ charset = doc.characterSet || doc.charset || "utf-8",
+ sandboxHtml = this._getHtml({
+ charset: charset,
+ stylesheets: this.config.stylesheets
+ });
+
+ // Create the basic dom tree including proper DOCTYPE and charset
+ iframeDocument.open("text/html", "replace");
+ iframeDocument.write(sandboxHtml);
+ iframeDocument.close();
+
+ this.getWindow = function() { return iframe.contentWindow; };
+ this.getDocument = function() { return iframe.contentWindow.document; };
+
+ // Catch js errors and pass them to the parent's onerror event
+ // addEventListener("error") doesn't work properly in some browsers
+ // TODO: apparently this doesn't work in IE9!
+ iframeWindow.onerror = function(errorMessage, fileName, lineNumber) {
+ throw new Error("wysihtml5.Sandbox: " + errorMessage, fileName, lineNumber);
+ };
+
+ if (!wysihtml5.browser.supportsSandboxedIframes()) {
+ // Unset a bunch of sensitive variables
+ // Please note: This isn't hack safe!
+ // It more or less just takes care of basic attacks and prevents accidental theft of sensitive information
+ // IE is secure though, which is the most important thing, since IE is the only browser, who
+ // takes over scripts & styles into contentEditable elements when copied from external websites
+ // or applications (Microsoft Word, ...)
+ var i, length;
+ for (i=0, length=windowProperties.length; i';
+ }
+ }
+ templateVars.stylesheets = html;
+
+ return wysihtml5.lang.string(
+ ''
+ + '#{stylesheets}'
+ + ''
+ ).interpolate(templateVars);
+ },
+
+ /**
+ * Method to unset/override existing variables
+ * @example
+ * // Make cookie unreadable and unwritable
+ * this._unset(document, "cookie", "", true);
+ */
+ _unset: function(object, property, value, setter) {
+ try { object[property] = value; } catch(e) {}
+
+ try { object.__defineGetter__(property, function() { return value; }); } catch(e) {}
+ if (setter) {
+ try { object.__defineSetter__(property, function() {}); } catch(e) {}
+ }
+
+ if (!wysihtml5.browser.crashesWhenDefineProperty(property)) {
+ try {
+ var config = {
+ get: function() { return value; }
+ };
+ if (setter) {
+ config.set = function() {};
+ }
+ Object.defineProperty(object, property, config);
+ } catch(e) {}
+ }
+ }
+ });
+})(wysihtml5);
+(function() {
+ var mapping = {
+ "className": "class"
+ };
+ wysihtml5.dom.setAttributes = function(attributes) {
+ return {
+ on: function(element) {
+ for (var i in attributes) {
+ element.setAttribute(mapping[i] || i, attributes[i]);
+ }
+ }
+ }
+ };
+})();wysihtml5.dom.setStyles = function(styles) {
+ return {
+ on: function(element) {
+ var style = element.style;
+ if (typeof(styles) === "string") {
+ style.cssText += ";" + styles;
+ return;
+ }
+ for (var i in styles) {
+ if (i === "float") {
+ style.cssFloat = styles[i];
+ style.styleFloat = styles[i];
+ } else {
+ style[i] = styles[i];
+ }
+ }
+ }
+ };
+};/**
+ * Simulate HTML5 placeholder attribute
+ *
+ * Needed since
+ * - div[contentEditable] elements don't support it
+ * - older browsers (such as IE8 and Firefox 3.6) don't support it at all
+ *
+ * @param {Object} parent Instance of main wysihtml5.Editor class
+ * @param {Element} view Instance of wysihtml5.views.* class
+ * @param {String} placeholderText
+ *
+ * @example
+ * wysihtml.dom.simulatePlaceholder(this, composer, "Foobar");
+ */
+(function(dom) {
+ dom.simulatePlaceholder = function(editor, view, placeholderText) {
+ var CLASS_NAME = "placeholder",
+ unset = function() {
+ if (view.hasPlaceholderSet()) {
+ view.clear();
+ }
+ dom.removeClass(view.element, CLASS_NAME);
+ },
+ set = function() {
+ if (view.isEmpty()) {
+ view.setValue(placeholderText);
+ dom.addClass(view.element, CLASS_NAME);
+ }
+ };
+
+ editor
+ .observe("set_placeholder", set)
+ .observe("unset_placeholder", unset)
+ .observe("focus:composer", unset)
+ .observe("paste:composer", unset)
+ .observe("blur:composer", set);
+
+ set();
+ };
+})(wysihtml5.dom);
+(function(dom) {
+ var documentElement = document.documentElement;
+ if ("textContent" in documentElement) {
+ dom.setTextContent = function(element, text) {
+ element.textContent = text;
+ };
+
+ dom.getTextContent = function(element) {
+ return element.textContent;
+ };
+ } else if ("innerText" in documentElement) {
+ dom.setTextContent = function(element, text) {
+ element.innerText = text;
+ };
+
+ dom.getTextContent = function(element) {
+ return element.innerText;
+ };
+ } else {
+ dom.setTextContent = function(element, text) {
+ element.nodeValue = text;
+ };
+
+ dom.getTextContent = function(element) {
+ return element.nodeValue;
+ };
+ }
+})(wysihtml5.dom);
+
+/**
+ * Fix most common html formatting misbehaviors of browsers implementation when inserting
+ * content via copy & paste contentEditable
+ *
+ * @author Christopher Blum
+ */
+wysihtml5.quirks.cleanPastedHTML = (function() {
+ // TODO: We probably need more rules here
+ var defaultRules = {
+ // When pasting underlined links into a contentEditable, IE thinks, it has to insert to keep the styling
+ "a u": wysihtml5.dom.replaceWithChildNodes
+ };
+
+ function cleanPastedHTML(elementOrHtml, rules, context) {
+ rules = rules || defaultRules;
+ context = context || elementOrHtml.ownerDocument || document;
+
+ var element,
+ isString = typeof(elementOrHtml) === "string",
+ method,
+ matches,
+ matchesLength,
+ i,
+ j = 0;
+ if (isString) {
+ element = wysihtml5.dom.getAsDom(elementOrHtml, context);
+ } else {
+ element = elementOrHtml;
+ }
+
+ for (i in rules) {
+ matches = element.querySelectorAll(i);
+ method = rules[i];
+ matchesLength = matches.length;
+ for (; j " ||
+ innerHTML == "