Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*******************************************************************************
*
* Copyright 2011-2014 Spiffy UI Team
*
* 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.
*
******************************************************************************/
/*
* The main JavaScript file for the Spiffy UI framework
*/
jQuery.fn.textWidth = function(){
var val = jQuery(this).val();
var span = jQuery('');
span.text(val); //safe html
jQuery(this).parent().append(span);
var width = span.width();
span.remove();
return width;
};
spiffyui = {
/*
* These four functions are for showing different kinds of messages
* in the general page UI. They are accessor methods for implementations
* in MessageUtil.java. They are bound in that same class.
*/
showFatalError: null,
showError: null,
showWarning: null,
showMessage: null,
/**
* This field controls the auto-loading of the Spiffy UI CSS
* references. If this values is false those references will
* not load. This value is true by default.
*/
autoloadCSS: true,
/**
* This field controls the auto-loading of the Spiffy UI DOM
* elements. If this values is false those DOM elements will
* not load. This value is true by default.
*/
autoloadHTML: true,
/**
* This field controls the enabling of the Spiffy UI browser
* history integration.
*/
historyEnabled: true,
/**
* This field gives users a chance to override the determined
* path for the CSS files loaded by spiffyui.js.
*
* If this value isn't specified then the CSS files will be
* loaded in the same path as the nocache.js file for this GWT
* application.
*
* If the autoloadCSS field is set to false then this field is
* not used.
*/
cssFilePath: null,
/**
* Gets a string of the date formatted into the short date
* format in the current locale.
*/
getDate: function(/*int*/ epoch) {
var dateVal = new Date(epoch);
return spiffyui.chineseAposWorkaround(dateVal.toString(Date.CultureInfo.formatPatterns.shortDate));
},
/**
* Gets a string of the date formatted into the specified format
*/
getDateString: function(/*int*/ epoch, /*string*/ format) {
var dateVal = new Date(epoch);
return spiffyui.chineseAposWorkaround(dateVal.toString(format));
},
/**
* Gets a string of the date formatted into the long date
* format in the current locale.
*/
getLongDate: function(/*int*/ epoch) {
var dateVal = new Date(epoch);
return spiffyui.chineseAposWorkaround(dateVal.toString(Date.CultureInfo.formatPatterns.longDate));
},
/**
* Gets a string of the date formatted into the month day
* format in the current locale. If abbrev = true, then use the
* abbreviation for month.
*/
getMonthDay: function(/*int*/ epoch, /*boolean*/ abbrev) {
var dateVal = new Date(epoch);
var dateFormat = Date.CultureInfo.formatPatterns.monthDay;
if (abbrev) {
dateFormat = dateFormat.replace("MMMM", "MMM");
}
return spiffyui.chineseAposWorkaround(dateVal.toString(dateFormat));
},
/**
* In zh locales the formatted date strings are
* surrounding every Chinese character with apostrophes.
* For example, it is showing, so this will remove all the
* apostrophes.
*/
chineseAposWorkaround: function(/*String*/ dateString) {
if (Date.CultureInfo.name.indexOf("zh") === 0 ||
Date.CultureInfo.name.indexOf("ja") === 0) {
return dateString.replace(/'/g, "");
}
return dateString;
},
/**
* Gets a string of the time formatted into the short time
* format in the current locale.
*/
getShortTime: function(/*int*/ epoch) {
var dateVal = new Date(epoch);
return spiffyui.midnightWorkaround(dateVal.toString(Date.CultureInfo.formatPatterns.shortTime));
},
/**
* Gets a string of the time at the hour or half hour or
* rounded up to the nearest half hour
* and formatted into the short time format in the current
* locale.
*/
getShortTimeRounded: function(/*int*/ epoch) {
var dateVal = new Date(epoch);
var min = dateVal.getMinutes();
if (min > 0) {
if (min < 30) {
dateVal.setMinutes(30);
} else if (min > 30) {
dateVal.setMinutes(0);
dateVal.setHours(dateVal.getHours() + 1);
}
}
return spiffyui.midnightWorkaround(dateVal.toString(Date.CultureInfo.formatPatterns.shortTime));
},
/**
* 12 AM is showing up as 0 AM, which is a bug in date.js, who is already aware of the problem.
* http://groups.google.com/group/datejs/browse_thread/thread/2d4f5d46916920a6/5e2106f2f911ea93?lnk=gst&q=0+AM#5e2106f2f911ea93
* Since we're still seeing the problem, applying hackito.
*/
midnightWorkaround: function (/*String*/ formattedString) {
var spaceLoc = formattedString.indexOf(' ');
if (formattedString.indexOf("0:") === 0 && formattedString.indexOf("AM") === 5) {
formattedString = formattedString.substring(2);
formattedString = "12:" + formattedString;
} else if (Date.CultureInfo.amDesignator !== '' && Date.CultureInfo.amDesignator.toLowerCase() !== 'am' && formattedString.indexOf(' ' + Date.CultureInfo.amDesignator + ' 00:') === spaceLoc) {
formattedString = formattedString.replace(Date.CultureInfo.amDesignator + ' 00:', Date.CultureInfo.amDesignator + ' 12:');
} else {
//If the time is not the first part of the string but instead preceded by a space
if (formattedString.indexOf(' 0:') === spaceLoc && formattedString.indexOf('AM') === spaceLoc + 6) {
formattedString = formattedString.replace(' 0:', ' 12:');
} else if (Date.CultureInfo.amDesignator !== '' && Date.CultureInfo.amDesignator.toLowerCase() !== 'am' && formattedString.indexOf(' ' + Date.CultureInfo.amDesignator + ' 00:') === spaceLoc) {
formattedString = formattedString.replace(Date.CultureInfo.amDesignator + ' 00:', Date.CultureInfo.amDesignator + ' 12:');
} else if (Date.CultureInfo.amDesignator.toLowerCase() === 'am') {
formattedString = formattedString.replace(' 00:', ' 12:').replace(' 0:', ' 12:');
}
}
return formattedString;
},
/**
* Gets a string of the date time formatted into the full date time
* format in the current locale.
*/
getDateTime: function(/*int*/ epoch) {
var dateVal = new Date(epoch);
return spiffyui.chineseAposWorkaround(spiffyui.midnightWorkaround(dateVal.toString(Date.CultureInfo.formatPatterns.fullDateTime)));
},
/**
* This is a helper function that gets a Date object from a time
* string like 11:30pm. This is just used in JSDateUtil and
* shouldn't be used anywhere else.
*/
getDateFromShortTime: function(/*string*/ formattedTime) {
/*
There is a bug in the date.js library where getting the time from a string with 'tt' that is not 'am' or 'pm'
(even though the amDesignator and pmDesignator are correct). So we change them to 'am' or 'pm'
before parsing.
*/
if (Date.CultureInfo.amDesignator !== '' &&
Date.CultureInfo.amDesignator.toLowerCase() !== 'am' &&
formattedTime.indexOf(Date.CultureInfo.amDesignator) >= 0) {
formattedTime = formattedTime.replace(Date.CultureInfo.amDesignator, 'AM');
}
if (Date.CultureInfo.pmDesignator !== '' &&
Date.CultureInfo.pmDesignator.toLowerCase() !== 'pm' &&
formattedTime.indexOf(Date.CultureInfo.pmDesignator) >= 0) {
formattedTime = formattedTime.replace(Date.CultureInfo.pmDesignator, 'PM');
}
/*
The date.js library has a bug where it gives the wrong
24 hour value for 12AM and 12PM. I've filed a bug report,
but we still need to work around the issue. Hackito
ergo sum.
*/
if (formattedTime.match(/12:[0-5][0-9] PM/) || formattedTime.match(/PM 12:[0-5][0-9]/)) {
formattedTime = formattedTime.replace("PM", "AM");
} else if (formattedTime.match(/12:[0-5][0-9] AM/) || formattedTime.match(/AM 12:[0-5][0-9]/)) {
formattedTime = formattedTime.replace("AM", "PM");
}
/*
There is also a bug with the timePicker where even if time is hh, it will only show h if
it's not 24 hour time. This is bogus because 01:00 AM should be allowed as well as 01:00 PM.
Let's make sure the hh is respected so Date.parseExact will be ok.
*/
var hhLoc = Date.CultureInfo.formatPatterns.shortTime.indexOf('hh:');
if (hhLoc >= 0) {
var colonLoc = formattedTime.indexOf(':');
if (colonLoc < hhLoc + 2) {
var hour = formattedTime.charAt(hhLoc);
formattedTime = formattedTime.replace(hour, '0' + hour);
}
}
/*
We want to make the Date class parse our time, but it does
like to parse time without the date so we put a bogus date
in front of it because we are just interested in the hours
and minutes.
*/
var date = Date.parseExact(new Date().toString("yyyy-MM-dd") + " " + formattedTime,
"yyyy-MM-dd " + Date.CultureInfo.formatPatterns.shortTime);
return date;
},
parseDateTime: function(/*String*/dateTimeString, /*String*/formatPattern) {
/*
* We need these objects to be strings so we can regex
* in the date and fix the 12 hour indicator to work around
* bugs from Date.js. These objects should always be strings,
* we want to code defensively.
*/
dateTimeString += '';
formatPattern += '';
/*
There is a bug in the date.js library where getting the time from a string with 'tt' that is not 'am' or 'pm'
(even though the amDesignator and pmDesignator are correct). So we change them to 'am' or 'pm'
before parsing.
*/
if (Date.CultureInfo.amDesignator !== '' &&
Date.CultureInfo.amDesignator.toLowerCase() !== 'am' &&
dateTimeString.indexOf(Date.CultureInfo.amDesignator) >= 0) {
dateTimeString = dateTimeString.replace(Date.CultureInfo.amDesignator, 'AM');
}
if (Date.CultureInfo.pmDesignator !== '' &&
Date.CultureInfo.pmDesignator.toLowerCase() !== 'pm' &&
dateTimeString.indexOf(Date.CultureInfo.pmDesignator) >= 0) {
dateTimeString = dateTimeString.replace(Date.CultureInfo.pmDesignator, 'PM');
}
/*
The date.js library has a bug where it gives the wrong
24 hour value for 12AM and 12PM. I've filed a bug report,
but we still need to work around the issue. Hackito
ergo sum.
*/
var orig12AM = false;
if (dateTimeString.match(/12:[0-5][0-9] PM/) || dateTimeString.match(/PM 12:[0-5][0-9]/)) {
dateTimeString = dateTimeString.replace("PM", "AM");
} else if (dateTimeString.match(/12:[0-5][0-9] P/)) {
dateTimeString = dateTimeString.replace("P", "AM");
} else if (dateTimeString.match(/12:[0-5][0-9] AM/) || dateTimeString.match(/AM 12:[0-5][0-9]/)) {
dateTimeString = dateTimeString.replace("AM", "PM");
orig12AM = true;
} else if (dateTimeString.match(/12:[0-5][0-9] A/)) {
dateTimeString = dateTimeString.replace("A", "PM");
orig12AM = true;
}
/*
There is also a bug with the timePicker where even if time is hh, it will only show h if
it's not 24 hour time. This is bogus because 01:00 AM should be allowed as well as 01:00 PM.
An example of this is zh-TW
*/
var hhLoc = formatPattern.indexOf('hh:');
if (hhLoc >= 0) {
var colonLoc = dateTimeString.indexOf(':');
if (colonLoc < hhLoc + 2) {
var hour = dateTimeString.charAt(hhLoc);
dateTimeString = dateTimeString.replace(' ' + hour + ':', ' 0' + hour + ':');
}
}
var date = Date.parseExact(dateTimeString, formatPattern);
if (date && orig12AM) {
/*
* Another bug in Date.js. Even after all the 12 am/pm workarounds,
* when it is originally 01/01/2012 12:00 AM
* we have to switch it to 01/01/2012 12:00 PM in order to get the time right
* but then it adds a whole other day! so we actually have to subract the day if the time was
* originally something 12:xx AM
*/
date = date.addDays(-1);
}
return date;
},
/**
* Gets a date that is set to the current date. The time is set to the start of the day (00:00 or 12:00 AM).
*/
getToday: function() {
return Date.today().getTime();
},
/**
* Adds the 1 day to today.
*/
nextDay: function() {
return Date.today().add(1).days().getTime();
},
/**
* Adds the specified number of units to the epochDate and returns the new epochDate
*/
dateAdd: function(/*int*/ epochDate, /*int*/amt, /*String*/unit) {
var date = new Date(epochDate);
if (unit === "WEEK") {
return date.addWeeks(amt).getTime();
} else if (unit === "MONTH") {
return date.addMonths(amt).getTime();
} else if (unit === "HOUR") {
return date.addHours(amt).getTime();
} else if (unit === "MINUTE") {
return date.addMinutes(amt).getTime();
} else if (unit === "SECOND") {
return date.addSeconds(amt).getTime();
} else if (unit === "YEAR") {
return date.addYears(amt).getTime();
} else {
return date.add(amt).days().getTime();
}
},
/**
* Gets the epoch string (milliseconds since 1970) from a date.
*/
getEpoch: function(/*date string*/ formattedDate) {
var epochObj = new Date(formattedDate);
return epochObj.getTime();
},
/**
* Get the Ordinal day (numeric day number) of the year, adjusted for leap year.
* Returns 1 through 365 (366 in leap years).
*/
getOrdinalNumber: function(/*int*/ epochDate) {
var date = new Date(epochDate);
return date.getDayOfYear();
},
/**
* Format the ID for a JQuery selector. This function adds a pound
* sign to the beginning of the string if there isn't on already
*/
formatId: function(/*string*/ id) {
if (id.indexOf('#') === 0) {
return id;
} else {
return '#' + id;
}
},
/**
* Get the UTC offset of the current browser timezone. This
* returns a number like -5 or 6
*/
getUTCOffset: function() {
var d = Date.today();
var offset = d.getUTCOffset();
if (offset.indexOf('+') === 0) {
return parseInt(offset.substring(1, offset.length - 2), 10);
} else if (offset.indexOf('-') === 0) {
return -parseInt(offset.substring(1, offset.length - 2), 10);
} else {
/*
* IE in some cases will return this value starting with undefined. That means
* negative.
*/
return -parseInt(offset.substring(10, offset.length - 2), 10);
}
},
/**
* Format the date specified and return the results
*
*/
formatDate: function(/*int*/ epochDate, /*string*/ formatter) {
return new Date(epochDate).format(formatter);
},
/**
* Add an item to the browser history. This function is just
* called from GWT.
*/
addHistoryItem: function(/*object*/ scope, /*string*/id, /*string*/url, /*string*/title,
/*boolean*/ bookmarkable, /*boolean*/ replace) {
if (!bookmarkable) {
url = '?-';
}
if (replace) {
spiffyui.History.replaceState({state:id}, title, url);
} else {
spiffyui.History.pushState({state:id}, title, url);
}
},
/**
* Go forward in the history
*/
forward: function() {
spiffyui.History.forward();
},
/**
* Go backward in the history
*/
back: function() {
spiffyui.History.back();
},
getHistoryState: function() {
return spiffyui.History.getState().data.state;
},
/**
* If X is negative go back through history X times, if X is
* positive go forwards through history X times
*/
go: function(/*int*/ x) {
spiffyui.History.go(x);
},
/**
* GWT often puts output files in a path with the module name.
* We need to determine that path so we can figure out where to
* reference our CSS files from. There isn't a great way to do
* this so we are looking for the nocache.js file and keying off
* of that path.
*/
getRelativePath: function() {
if (spiffyui.cssFilePath) {
return spiffyui.cssFilePath;
}
var path = '';
jQuery('script').each(function() {
if (jQuery(this).attr('src') && jQuery(this).attr('src').indexOf('nocache.js') > -1) {
if (jQuery(this).attr('src').indexOf('/') === -1) {
return;
} else {
path = jQuery(this).attr('src').substring(0, jQuery(this).attr('src').lastIndexOf('/') + 1);
}
}
});
return path;
},
/**
* This method is a little tricky. It needs to get the current URL of the application
* so we can build the right location to the oauth.html file for OAuth redirection. To
* do that we combine the current protocol, host, and path with the relative URL for the
* nocache.js file so we can get the right location of where GWT will put the oauth.html
* file instead of where the GWT application front page is loaded from.
*/
getCurrentUrl: function() {
var url = window.location.protocol + "//" + window.location.host + window.location.pathname;
if (window.location.pathname.length > 0 && url.substring(url.length - 1) !== '/') {
/*
* Then the URL ends with something like index.html.
*/
url = url.substring(0, url.lastIndexOf('/') + 1);
}
url += spiffyui.getRelativePath();
if (url.substring(url.length - 1) !== '/') {
url += '/';
}
return url;
},
oAuthAuthenticate: function(/*String*/ url, /*String*/ clientId, /*String*/ scope, /*boolean*/ sendRedirect, /*function*/ callback) {
window.addEventListener('message', spiffyui.oAuthAuthenticateCompleteEventListener, false);
//spiffyui.log('oAuthAuthenticate(' + url + ', ' + clientId + ', ' + scope + ')');
spiffyui.oauthCallback = callback;
url += '?response_type=token';
if (sendRedirect) {
url += '&redirect_uri=' + spiffyui.getCurrentUrl() + 'oauth.html';
}
if (clientId) {
url += '&client_id=' + clientId;
}
if (scope) {
url += '&scope=' + scope;
}
spiffyui.oauthstate = 'spiffystate' + Math.random();
url += '&state=' + spiffyui.oauthstate;
//spiffyui.log('spiffyui.oauthstate: ' + spiffyui.oauthstate);
//spiffyui.log('url: ' + url);
var frame = $('');
frame.css({
'position': 'fixed',
'left': '0px',
'top': '0px',
'z-index': '99999',
'width': '100%',
'height': '100%'
});
if (navigator.userAgent.match(/iPhone/i)) {
/*
* We show the OAuth login dialog with an iFrame and we use
* fixed positioning so the frame stays over the main screen.
* This works well almost everywhere, but iPhone doesn't allow
* you to scroll fixed position items so we use absolute
* positioning on iPhone. What a hack.
*/
frame.css('position', 'absolute');
}
$('body').append(frame);
},
oAuthAuthenticateCompleteEventListener: function(event) {
window.removeEventListener('message', spiffyui.oAuthAuthenticateCompleteEventListener, false);
spiffyui.oAuthAuthenticateComplete(event.data);
},
oAuthAuthenticateComplete: function(/*String*/ response) {
//spiffyui.log('oAuthAuthenticateComplete(' + response + ')');
var callback = spiffyui.oauthCallback;
spiffyui.oauthCallback = null;
$('#spiffyuoauthframe').remove();
// First, parse the query string
var params = {};
var queryString = response.substring(1);
//spiffyui.log('queryString: ' + queryString);
var regex = /([^&=]+)=([^&]*)/g;
var m = regex.exec(queryString);
while (m) {
//spiffyui.log('m[1]: ' + m[1]);
//spiffyui.log('m[2]: ' + m[2]);
params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
m = regex.exec(queryString);
}
//spiffyui.log('params.state: ' + params.state);
//spiffyui.log('params.access_token: ' + params.access_token);
//spiffyui.log('params.token_type: ' + params.token_type);
if (spiffyui.oauthstate !== params.state) {
spiffyui.oauthstate = null;
callback("invalidstate", "null");
} else {
spiffyui.oauthstate = null;
callback(params.access_token, params.token_type);
}
},
log: function(/*String*/ msg) {
if (console && console.log) {
console.log(msg);
}
},
init: function() {
spiffyui.isMobile = navigator.userAgent.match(/iPad/i) !== null ||
navigator.userAgent.match(/iPhone/i) !== null ||
navigator.userAgent.match(/iPad/i) !== null ||
navigator.userAgent.match(/iPod/i) !== null ||
navigator.userAgent.match(/android/i) !== null;
if (spiffyui.autoloadHTML) {
/*
* We start by adding the HTML tags our CSS depends on
*/
jQuery('body').append(
'' +
'
' +
'
' +
'' +
'
' +
'' +
'' +
'' +
'
' +
'' +
'
' +
'
' +
'');
}
var path = spiffyui.getRelativePath();
if (spiffyui.autoloadCSS) {
/*
* Almost all of our CSS is in spiffyui.css, but there are always a few
* tweaks you need to add for IE. This special style sheet is added only
* if the browser is IE and contains just those tweaks.
*/
if (navigator.appName === 'Microsoft Internet Explorer' || navigator.userAgent.toLowerCase().match(/trident.+rv:11./)) {
jQuery('head').prepend('');
css = jQuery('head').children(':first');
css.attr({
rel: 'stylesheet',
type: 'text/css',
href: path + 'spiffyui.ie.css'
});
}
/*
* Now we add the spiffyui.min.css file. If the URL ends with -debug.html
* then we'll add the uncompressed version. We add these files dynamically
* so users of the framework have less to add to their page and because IE8
* give precedence to files loaded in the page over those added with JavaScript
* and we can't do that because we override styles in spiffyui.ie.css.
*/
if (window.location.href.indexOf('-debug.htm') > -1) {
jQuery('head').prepend('');
css = jQuery('head').children(':first');
css.attr({
rel: 'stylesheet',
type: 'text/css',
href: path + 'spiffyui.css'
});
} else {
jQuery('head').prepend('');
css = jQuery('head').children(':first');
css.attr({
rel: 'stylesheet',
type: 'text/css',
href: path + 'spiffyui.min.css'
});
}
}
/*
* The last step is to initialize our history framework.
*/
(function(window) {
spiffyui.History = window.History; // Note: We are using a capital H instead of a lower h
if (!spiffyui.historyEnabled) {
spiffyui.log("SpiffyUI history integration is disabled.");
/*
* Applications aren't required to use our history support and if
* they haven't loaded the libraries then we don't want to try
* and call them.
*/
return false;
}
// Bind to StateChange Event
spiffyui.History.Adapter.bind(window,'statechange',function() { // Note: We are using statechange instead of popstate
var State = spiffyui.History.getState(); // Note: We are using History.getState() instead of event.state
if (spiffyui.doHandleHistoryEvent) {
/*
* If the doHandleHistoryEvent function has been bound then we
* call Spiffy UI to handle the history event.
*/
spiffyui.doHandleHistoryEvent(State.data.state);
}
});
}(window));
}
};
jQuery(document).ready(function() {
spiffyui.init();
});