Add JS files

This commit is contained in:
2025-05-12 15:45:17 +00:00
parent 7ddd15c4fa
commit 967007b0c7
3239 changed files with 1157078 additions and 0 deletions

View File

@@ -0,0 +1,217 @@
/*
Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
json.js
The global object JSON contains two methods.
JSON.stringify(value) takes a JavaScript value and produces a JSON text.
The value must not be cyclical.
JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
return false if there is an error.
2008-10-10: New regular expressions copied in from the new json2.js file on http://json.org (released into the public domain), work better on Safari and IE for more complicated datasets
*/
var JSON = function () {
var m = {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
s = {
array: function (x) {
var a = ['['], b, f, i, l = x.length, v;
for (i = 0; i < l; i += 1) {
v = x[i];
f = s[typeof v];
if (f) {
v = f(v);
if (typeof v == 'string') {
if (b) {
a[a.length] = ',';
}
a[a.length] = v;
b = true;
}
}
}
a[a.length] = ']';
return a.join('');
},
'boolean': function (x) {
return String(x);
},
'null': function (x) {
return "null";
},
number: function (x) {
return isFinite(x) ? String(x) : 'null';
},
object: function (x) {
if (x) {
if (x instanceof Array) {
return s.array(x);
}
var a = ['{'], b, f, i, v;
for (i in x) {
if (!x.hasOwnProperty || x.hasOwnProperty(i)) {
v = x[i];
f = s[typeof v];
if (f) {
v = f(v);
if (typeof v == 'string') {
if (b) {
a[a.length] = ',';
}
a.push(s.string(i), ':', v);
b = true;
}
}
}
}
a[a.length] = '}';
return a.join('');
}
return 'null';
},
string: function (x) {
var unicode = new String;
for(var i=0; i<x.length; i++) {
var temp = x.charCodeAt(i).toString(16) ;
while(temp.length < 4) {
temp = "0" + temp;
}
unicode += '\\u' + temp;
}
return '"' + unicode + '"';
}
};
return {
/*
Stringify a JavaScript value, adding a security envelope, producing a JSON text.
*/
stringify: function (v) {
var f = s[typeof v];
if (f) {
v = f(v);
if (typeof v === 'string') {
// cn: bug 12274 - add a security envelope to protect against CSRF
var securityEnvelope = "{asynchronous_key:'" + asynchronous_key +"', jsonObject:" + v + "}";
return securityEnvelope;
}
}
return;
},
destringify: function(str) {
},
/*
Stringify a JavaScript value, NO security envelope, producing a JSON text.
*/
stringifyNoSecurity : function (v) {
var f = s[typeof v];
if (f) {
v = f(v);
if (typeof v === 'string') {
return v;
}
}
return;
},
destringify: function(str) {
},
/*
Parse a JSON text, producing a JavaScript value.
It returns false if there is a syntax error.
*/
parse: function (text) {
// mfh: bug 14599
text = text.replace(/^\s*|\s*$/,'');
// cn: bug 12274 - the below defend against CSRF (see desc for whitepaper)
if(text.substr) {
if(text.substr(0,11) == "while(1);/*") {
text = text.substr(11);
text = text.substr(0, (text.length - 2));
}
}
try {
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/.test(text
.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
return eval('(' + text + ')');
} else {
return false;
}
} catch (e) {
return false;
}
},
/**
* SUGAR: in response to CSRF, keep a standard copy of the parse function
*/
parseNoSecurity: function (text) {
try {
// See the comments in the above function for a description of what this mess is
if (/^[\],:{}\s]*$/.test(text
.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
return eval('(' + text + ')');
} else {
return false;
}
} catch (e) {
return false;
}
}
};
}();

View File

@@ -0,0 +1,650 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
SUGAR.mySugar = function() {
var originalLayout = null;
var configureDashletId = null;
var currentDashlet = null;
var leftColumnInnerHTML = null;
var leftColObj = null;
var maxCount;
var warningLang;
var activeTab = activePage;
var current_user = current_user_id;
var module = moduleName;
var charts = new Object();
if (module == 'Dashboard'){
cookiePageIndex = current_user + "_activeDashboardPage";
}
else{
cookiePageIndex = current_user + "_activePage";
}
var homepage_dd;
return {
clearChartsArray: function(){
charts[activeTab] = new Object();
},
addToChartsArray: function(name, xmlFile, width, height, styleSheet, colorScheme, langFile){
if (charts[activeTab] == null){
charts[activeTab] = new Object();
}
charts[activeTab][name] = new Object();
charts[activeTab][name]['name'] = name;
charts[activeTab][name]['xmlFile'] = xmlFile;
charts[activeTab][name]['width'] = width;
charts[activeTab][name]['height'] = height;
charts[activeTab][name]['styleSheet'] = styleSheet;
charts[activeTab][name]['colorScheme'] = colorScheme;
charts[activeTab][name]['langFile'] = langFile;
},
loadSugarChart: function(name, xmlFile, width, height, styleSheet, colorScheme, langFile){
loadChartSWF(name, xmlFile, width, height, styleSheet, colorScheme, langFile);
},
loadSugarCharts: function(){
for (id in charts[activeTab]){
if(id != 'undefined'){
SUGAR.mySugar.loadSugarChart(charts[activeTab][id]['name'],
charts[activeTab][id]['xmlFile'],
charts[activeTab][id]['width'],
charts[activeTab][id]['height'],
charts[activeTab][id]['styleSheet'],
charts[activeTab][id]['colorScheme'],
charts[activeTab][id]['langFile']);
}
}
},
// get the current dashlet layout
getLayout: function(asString) {
columns = new Array();
for(je = 0; je < 3; je++) {
dashlets = document.getElementById('col_'+activeTab+'_'+ je);
if (dashlets != null){
dashletIds = new Array();
for(wp = 0; wp < dashlets.childNodes.length; wp++) {
if(typeof dashlets.childNodes[wp].id != 'undefined' && dashlets.childNodes[wp].id.match(/dashlet_[\w-]*/)) {
dashletIds.push(dashlets.childNodes[wp].id.replace(/dashlet_/,''));
}
}
if(asString)
columns[je] = dashletIds.join(',');
else
columns[je] = dashletIds;
}
}
if(asString) return columns.join('|');
else return columns;
},
// called when dashlet is picked up
onDrag: function(e, id) {
originalLayout = SUGAR.mySugar.getLayout(true);
},
// called when dashlet is dropped
onDrop: function(e, id) {
newLayout = SUGAR.mySugar.getLayout(true);
if(originalLayout != newLayout) { // only save if the layout has changed
SUGAR.mySugar.saveLayout(newLayout);
SUGAR.mySugar.loadSugarCharts(); // called safely because there is a check to be sure the array exists
}
},
// save the layout of the dashlet
saveLayout: function(order) {
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING_LAYOUT'));
var success = function(data) {
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVED_LAYOUT'));
window.setTimeout('ajaxStatus.hideStatus()', 2000);
}
url = 'index.php?to_pdf=1&module='+module+'&action=DynamicAction&DynamicAction=saveLayout&layout=' + order + '&selectedPage=' + activeTab;
var cObj = YAHOO.util.Connect.asyncRequest('GET', url, {success: success, failure: success});
},
uncoverPage: function(id) {
if (!SUGAR.isIE){
document.getElementById('dlg_c').style.display = 'none';
}
configureDlg.hide();
if ( document.getElementById('dashletType') == null ) {
dashletType = '';
} else {
dashletType = document.getElementById('dashletType').value;
}
SUGAR.mySugar.retrieveDashlet(SUGAR.mySugar.configureDashletId, dashletType);
},
// call to configure a Dashlet
configureDashlet: function(id) {
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_LOADING'));
configureDlg = new YAHOO.widget.SimpleDialog("dlg",
{ visible:false,
width:"510",
effect:[{effect:YAHOO.widget.ContainerEffect.SLIDE, duration:0.5},
{effect:YAHOO.widget.ContainerEffect.FADE,duration:0.5}],
fixedcenter:true,
modal:true,
draggable:false }
);
fillInConfigureDiv = function(data){
ajaxStatus.hideStatus();
// uncomment the line below to debug w/ FireBug
// console.log(data.responseText);
try {
eval(data.responseText);
}
catch(e) {
result = new Array();
result['header'] = 'error';
result['body'] = 'There was an error handling this request.';
}
configureDlg.setHeader(result['header']);
configureDlg.setBody(result['body']);
var listeners = new YAHOO.util.KeyListener(document, { keys : 27 }, {fn: function() {this.hide();}, scope: configureDlg, correctScope:true} );
configureDlg.cfg.queueProperty("keylisteners", listeners);
configureDlg.render(document.body);
configureDlg.show();
configureDlg.configFixedCenter(null, false) ;
SUGAR.util.evalScript(result['body']);
}
SUGAR.mySugar.configureDashletId = id; // save the id of the dashlet being configured
var cObj = YAHOO.util.Connect.asyncRequest('GET','index.php?to_pdf=1&module='+module+'&action=DynamicAction&DynamicAction=configureDashlet&id=' + id,
{success: fillInConfigureDiv, failure: fillInConfigureDiv}, null);
},
/** returns dashlets contents
* if url is defined, dashlet will be retrieve with it, otherwise use default url
*
* @param string id id of the dashlet to refresh
* @param string url url to be used
* @param function callback callback function after refresh
* @param bool dynamic does the script load dynamic javascript, set to true if you user needs to refresh the dashlet after load
*/
retrieveDashlet: function(id, url, callback, dynamic) {
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_LOADING'));
if(!url) {
url = 'index.php?action=DynamicAction&DynamicAction=displayDashlet&module='+module+'&to_pdf=1&id=' + id;
is_chart_dashlet = false;
}
else if (url == 'predefined_chart'){
url = 'index.php?action=DynamicAction&DynamicAction=displayDashlet&module='+module+'&to_pdf=1&id=' + id;
scriptUrl = 'index.php?action=DynamicAction&DynamicAction=getPredefinedChartScript&module='+module+'&to_pdf=1&id=' + id;
is_chart_dashlet = true;
}
if(dynamic) {
url += '&dynamic=true';
}
var fillInDashlet = function(data) {
ajaxStatus.hideStatus();
if(data) {
SUGAR.mySugar.currentDashlet.innerHTML = data.responseText;
}
SUGAR.util.evalScript(data.responseText);
if(callback) callback();
var processChartScript = function(scriptData){
SUGAR.util.evalScript(scriptData.responseText);
SUGAR.mySugar.loadSugarChart(charts[activeTab][id]['name'],
charts[activeTab][id]['xmlFile'],
charts[activeTab][id]['width'],
charts[activeTab][id]['height'],
charts[activeTab][id]['styleSheet'],
charts[activeTab][id]['colorScheme'],
charts[activeTab][id]['langFile']);
}
if(typeof(is_chart_dashlet)=='undefined'){
is_chart_dashlet = false;
}
if (is_chart_dashlet){
var chartScriptObj = YAHOO.util.Connect.asyncRequest('GET', scriptUrl,
{success: processChartScript, failure: processChartScript}, null);
}
}
SUGAR.mySugar.currentDashlet = document.getElementById('dashlet_entire_' + id);
var cObj = YAHOO.util.Connect.asyncRequest('GET', url,
{success: fillInDashlet, failure: fillInDashlet}, null);
return false;
},
// for the display columns widget
setChooser: function() {
var displayColumnsDef = new Array();
var hideTabsDef = new Array();
var left_td = document.getElementById('display_tabs_td');
var right_td = document.getElementById('hide_tabs_td');
var displayTabs = left_td.getElementsByTagName('select')[0];
var hideTabs = right_td.getElementsByTagName('select')[0];
for(i = 0; i < displayTabs.options.length; i++) {
displayColumnsDef.push(displayTabs.options[i].value);
}
if(typeof hideTabs != 'undefined') {
for(i = 0; i < hideTabs.options.length; i++) {
hideTabsDef.push(hideTabs.options[i].value);
}
}
document.getElementById('displayColumnsDef').value = displayColumnsDef.join('|');
document.getElementById('hideTabsDef').value = hideTabsDef.join('|');
},
deleteDashlet: function(id) {
if(confirm(SUGAR.language.get('app_strings', 'LBL_REMOVE_DASHLET_CONFIRM'))) {
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_REMOVING_DASHLET'));
del = function() {
var success = function(data) {
dashlet = document.getElementById('dashlet_' + id);
dashlet.parentNode.removeChild(dashlet);
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_REMOVED_DASHLET'));
window.setTimeout('ajaxStatus.hideStatus()', 2000);
}
var cObj = YAHOO.util.Connect.asyncRequest('GET','index.php?to_pdf=1&module='+module+'&action=DynamicAction&DynamicAction=deleteDashlet&activePage=' + activeTab + '&id=' + id,
{success: success, failure: success}, null);
}
var anim = new YAHOO.util.Anim('dashlet_entire_' + id, { height: {to: 1} }, .5 );
anim.onComplete.subscribe(del);
document.getElementById('dashlet_entire_' + id).style.overflow = 'hidden';
anim.animate();
return false;
}
return false;
},
addDashlet: function(id, type, type_module) {
ajaxStatus.hideStatus();
columns = SUGAR.mySugar.getLayout();
var num_dashlets = columns[0].length;
if (typeof columns[1] == undefined){
num_dashlets = num_dashlets + columns[1].length;
}
if((num_dashlets) >= SUGAR.mySugar.maxCount) {
alert(SUGAR.language.get('app_strings', 'LBL_MAX_DASHLETS_REACHED'));
return;
}
/* if((columns[0].length + columns[1].length) >= SUGAR.mySugar.maxCount) {
alert(SUGAR.language.get('Home', 'LBL_MAX_DASHLETS_REACHED'));
return;
}*/
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_ADDING_DASHLET'));
var success = function(data) {
colZero = document.getElementById('col_'+activeTab+'_0');
newDashlet = document.createElement('li'); // build the list item
newDashlet.id = 'dashlet_' + data.responseText;
newDashlet.className = 'noBullet active';
// hide it first, but append to getRegion
newDashlet.innerHTML = '<div style="position: absolute; top: -1000px; overflow: hidden;" id="dashlet_entire_' + data.responseText + '"></div>';
colZero.insertBefore(newDashlet, colZero.firstChild); // insert it into the first column
var finishRetrieve = function() {
dashletEntire = document.getElementById('dashlet_entire_' + data.responseText);
dd = new ygDDList('dashlet_' + data.responseText); // make it draggable
dd.setHandleElId('dashlet_header_' + data.responseText);
dd.onMouseDown = SUGAR.mySugar.onDrag;
dd.onDragDrop = SUGAR.mySugar.onDrop;
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_ADDED_DASHLET'));
dashletRegion = YAHOO.util.Dom.getRegion(dashletEntire);
dashletEntire.style.position = 'relative';
dashletEntire.style.height = '1px';
dashletEntire.style.top = '0px';
dashletEntire.className = 'dashletPanel';
var anim = new YAHOO.util.Anim('dashlet_entire_' + data.responseText, { height: {to: dashletRegion.bottom - dashletRegion.top} }, .5 );
anim.onComplete.subscribe(function() { document.getElementById('dashlet_entire_' + data.responseText).style.height = '100%'; });
anim.animate();
window.setTimeout('ajaxStatus.hideStatus()', 2000);
}
if (type == 'module' || type == 'web'){
url = null;
type = 'module';
}
else if (type == 'predefined_chart'){
url = 'predefined_chart';
type = 'predefined_chart';
}
else if (type == 'chart'){
url = 'chart';
type = 'chart';
}
SUGAR.mySugar.retrieveDashlet(data.responseText, url, finishRetrieve, true); // retrieve it from the server
newLayout = SUGAR.mySugar.getLayout(true);
SUGAR.mySugar.saveLayout(newLayout);
}
var cObj = YAHOO.util.Connect.asyncRequest('GET','index.php?to_pdf=1&module='+module+'&action=DynamicAction&DynamicAction=addDashlet&activeTab=' + activeTab + '&id=' + id+'&type=' + type + '&type_module=' + type_module,
{success: success, failure: success}, null);
return false;
},
showDashletsDialog: function() {
columns = SUGAR.mySugar.getLayout();
var num_dashlets = 0;
var i = 0;
for ( i = 0 ; i < 3; i++ ) {
if (typeof columns[i] != "undefined") {
num_dashlets = num_dashlets + columns[i].length;
}
}
if((num_dashlets) >= SUGAR.mySugar.maxCount) {
alert(SUGAR.language.get('app_strings', 'LBL_MAX_DASHLETS_REACHED'));
return;
}
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_LOADING'));
var success = function(data) {
eval(data.responseText);
dashletsListDiv = document.getElementById('dashletsList');
dashletsListDiv.innerHTML = response['html'];
document.getElementById('dashletsDialog_c').style.display = '';
SUGAR.mySugar.dashletsDialog.show();
eval(response['script']);
ajaxStatus.hideStatus();
}
var cObj = YAHOO.util.Connect.asyncRequest('GET', 'index.php?to_pdf=true&module='+module+'&action=DynamicAction&DynamicAction=dashletsDialog', {success: success, failure: success});
return false;
},
closeDashletsDialog: function(){
SUGAR.mySugar.dashletsDialog.hide();
window.setTimeout("document.getElementById('dashletsDialog_c').style.display = 'none';", 2000);
},
toggleDashletCategories: function(category){
document.getElementById('search_string').value = '';
document.getElementById('searchResults').innerHTML = '';
var moduleTab = document.getElementById('moduleCategory');
var moduleTabAnchor = document.getElementById('moduleCategoryAnchor');
var moduleListDiv = document.getElementById('moduleDashlets');
var chartTab = document.getElementById('chartCategory');
var chartTabAnchor = document.getElementById('chartCategoryAnchor');
var chartListDiv = document.getElementById('chartDashlets');
var toolsTab = document.getElementById('toolsCategory');
var toolsTabAnchor = document.getElementById('toolsCategoryAnchor');
var toolsListDiv = document.getElementById('toolsDashlets');
var webTab = document.getElementById('webCategory');
var webTabAnchor = document.getElementById('webCategoryAnchor');
var webListDiv = document.getElementById('webDashlets');
switch(category){
case 'module':
moduleTab.className = 'active';
moduleTabAnchor.className = 'current';
moduleListDiv.style.display = '';
chartTab.className = '';
chartTabAnchor.className = '';
chartListDiv.style.display = 'none';
toolsTab.className = '';
toolsTabAnchor.className = '';
toolsListDiv.style.display = 'none';
webTab.className = '';
webTabAnchor.className = '';
webListDiv.style.display = 'none';
break;
case 'chart':
moduleTab.className = '';
moduleTabAnchor.className = '';
moduleListDiv.style.display = 'none';
chartTab.className = 'active';
chartTabAnchor.className = 'current';
chartListDiv.style.display = '';
toolsTab.className = '';
toolsTabAnchor.className = '';
toolsListDiv.style.display = 'none';
webTab.className = '';
webTabAnchor.className = '';
webListDiv.style.display = 'none';
break;
case 'tools':
moduleTab.className = '';
moduleTabAnchor.className = '';
moduleListDiv.style.display = 'none';
chartTab.className = '';
chartTabAnchor.className = '';
chartListDiv.style.display = 'none';
toolsTab.className = 'active';
toolsTabAnchor.className = 'current';
toolsListDiv.style.display = '';
webTab.className = '';
webTabAnchor.className = '';
webListDiv.style.display = 'none';
break;
case 'web':
moduleTab.className = '';
moduleTabAnchor.className = '';
moduleListDiv.style.display = 'none';
chartTab.className = '';
chartTabAnchor.className = '';
chartListDiv.style.display = 'none';
toolsTab.className = '';
toolsTabAnchor.className = '';
toolsListDiv.style.display = 'none';
webTab.className = 'active';
webTabAnchor.className = 'current';
webListDiv.style.display = '';
break;
default:
break;
}
document.getElementById('search_category').value = category;
},
searchDashlets: function(searchStr, searchCategory){
var moduleTab = document.getElementById('moduleCategory');
var moduleTabAnchor = document.getElementById('moduleCategoryAnchor');
var moduleListDiv = document.getElementById('moduleDashlets');
var chartTab = document.getElementById('chartCategory');
var chartTabAnchor = document.getElementById('chartCategoryAnchor');
var chartListDiv = document.getElementById('chartDashlets');
var toolsTab = document.getElementById('toolsCategory');
var toolsTabAnchor = document.getElementById('toolsCategoryAnchor');
var toolsListDiv = document.getElementById('toolsDashlets');
if (moduleTab != null && chartTab != null && toolsTab != null){
moduleListDiv.style.display = 'none';
chartListDiv.style.display = 'none';
toolsListDiv.style.display = 'none';
}
// dashboards case, where there are no tabs
else{
chartListDiv.style.display = 'none';
}
var searchResultsDiv = document.getElementById('searchResults');
searchResultsDiv.style.display = '';
var success = function(data) {
eval(data.responseText);
searchResultsDiv.innerHTML = response['html'];
}
var cObj = YAHOO.util.Connect.asyncRequest('GET', 'index.php?to_pdf=true&module='+module+'&action=DynamicAction&DynamicAction=searchDashlets&search='+searchStr+'&category='+searchCategory, {success: success, failure: success});
return false;
},
collapseList: function(chartList){
document.getElementById(chartList+'List').style.display='none';
document.getElementById(chartList+'ExpCol').innerHTML = '<a href="#" onClick="javascript:SUGAR.mySugar.expandList(\''+chartList+'\');"><img border="0" src="' + SUGAR.themes.image_server + 'index.php?entryPoint=getImage&themeName='+SUGAR.themes.theme_name+'&imageName=advanced_search.gif" align="absmiddle" />';
},
expandList: function(chartList){
document.getElementById(chartList+'List').style.display='';
document.getElementById(chartList+'ExpCol').innerHTML = '<a href="#" onClick="javascript:SUGAR.mySugar.collapseList(\''+chartList+'\');"><img border="0" src="' + SUGAR.themes.image_server + 'index.php?entryPoint=getImage&themeName='+SUGAR.themes.theme_name+'&imageName=basic_search.gif" align="absmiddle" />';
},
collapseReportList: function(reportChartList){
document.getElementById(reportChartList+'ReportsChartDashletsList').style.display='none';
document.getElementById(reportChartList+'ExpCol').innerHTML = '<a href="#" onClick="javascript:SUGAR.mySugar.expandReportList(\''+reportChartList+'\');"><img border="0" src="' + SUGAR.themes.image_server + 'index.php?entryPoint=getImage&themeName='+SUGAR.themes.theme_name+'&imageName=ProjectPlus.gif" align="absmiddle" />';
},
expandReportList: function(reportChartList){
document.getElementById(reportChartList+'ReportsChartDashletsList').style.display='';
document.getElementById(reportChartList+'ExpCol').innerHTML = '<a href="#" onClick="javascript:SUGAR.mySugar.collapseReportList(\''+reportChartList+'\');"><img border="0" src="' + SUGAR.themes.image_server + 'index.php?entryPoint=getImage&themeName='+SUGAR.themes.theme_name+'&imageName=ProjectMinus.gif" align="absmiddle" />';
},
clearSearch: function(){
document.getElementById('search_string').value = '';
var moduleTab = document.getElementById('moduleCategory');
var moduleTabAnchor = document.getElementById('moduleCategoryAnchor');
var moduleListDiv = document.getElementById('moduleDashlets');
document.getElementById('searchResults').innerHTML = '';
if (moduleTab != null){
SUGAR.mySugar.toggleDashletCategories('module');
}
else{
document.getElementById('searchResults').style.display = 'none';
document.getElementById('chartDashlets').style.display = '';
}
},
doneAddDashlets: function() {
SUGAR.mySugar.dashletsDialog.hide();
return false;
},
renderDashletsDialog: function(){
SUGAR.mySugar.dashletsDialog = new YAHOO.widget.Dialog("dashletsDialog",
{ width : "480px",
height: "520px",
fixedcenter : true,
draggable:false,
visible : false,
// effect:[{effect:YAHOO.widget.ContainerEffect.SLIDETOP, duration:0.5},{effect:YAHOO.widget.ContainerEffect.FADE,duration:0.5}],
modal : true,
close:false
} );
var listeners = new YAHOO.util.KeyListener(document, { keys : 27 }, {fn: function() {SUGAR.mySugar.closeDashletsDialog();} } );
SUGAR.mySugar.dashletsDialog.cfg.queueProperty("keylisteners", listeners);
document.getElementById('dashletsDialog').style.display = '';
SUGAR.mySugar.dashletsDialog.render();
document.getElementById('dashletsDialog_c').style.display = 'none';
}
};
}();

View File

@@ -0,0 +1,715 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
var request_id = 0;
var current_child_field = '';
var current_subpanel_url = '';
var child_field_loaded = new Object();
var request_map = new Object();
function get_module_name()
{
if(typeof(window.document.forms['DetailView']) == 'undefined') {
return '';
} else {
//check to see if subpanel_parent_module input exists. If so override module name
//this is used in the case when the subpanel contents are of the same module as the current module
//and the record in $_REQUEST is of the parent object. By specifying the subpanel_parent_module,
//you allow normal processing to continue. For an example, see trackdetailview.html/php in campaigns module
if(typeof(window.document.forms['DetailView'].elements['subpanel_parent_module']) != 'undefined' &&
window.document.forms['DetailView'].elements['subpanel_parent_module'].value != ''){
return window.document.forms['DetailView'].elements['subpanel_parent_module'].value;
}
return window.document.forms['DetailView'].elements['module'].value;
}
}
/*this function will take in three parameters, m,i,a and recreate navigation
* m = module
* i = record id
* a = action (detail/edit)
* t = element to be modified
* r = relationship to update after edit.
* This is done to minimize page size
* */
function subp_nav(m,i,a,t,r){
if(t.href.search(/#/) < 0){
//no need to process if url has already been converted
return;
}
if(a=='d'){
a='DetailView';
}else{
a='EditView';
}
url = "index.php?module="+m+"&action="+a+"&record="+i+"&parent_module="+get_module_name()+"&parent_id="+get_record_id()+"&return_module="+get_module_name()+"&return_id="+get_record_id()+"&return_action=DetailView";
if (r)
{
url += "&return_relationship=" + r;
}
t.href = url;
}
/*this function will take in three parameters, m,i,a and recreate navigation
* m = module
* i = record id
* a = action (detail/edit)
* This is done to minimize page size
* */
function sub_p_rem(sp,lf,li,rp){
return_url = "index.php?module="+get_module_name()+"&action=SubPanelViewer&subpanel="+sp+"&record="+get_record_id()+"&sugar_body_only=1&inline=1";
remove_url = "index.php?module="+ get_module_name()
+ "&action=DeleteRelationship"
+ "&record="+ get_record_id()
+ "&linked_field="+ lf //$linked_field"
+ "&linked_id="+ li //$record"
+ "&return_url=" + escape(escape(return_url))
+ "&refresh_page=" + rp;//$refresh_page"
showSubPanel(sp,remove_url,true);
}
function sp_rem_conf(){
return confirm(SUGAR.language.get('app_strings', 'NTC_REMOVE_CONFIRMATION'))
}
function get_record_id()
{
return window.document.forms['DetailView'].elements['record'].value;
}
function get_layout_def_key()
{
if(typeof(window.document.forms['DetailView'].elements['layout_def_key']) == 'undefined')return '';
return window.document.forms['DetailView'].elements['layout_def_key'].value;
}
function save_finished(args)
{
var child_field = request_map[args.request_id];
delete (child_field_loaded[child_field] );
showSubPanel(child_field);
}
function set_return_and_save_background(popup_reply_data)
{
var form_name = popup_reply_data.form_name;
var name_to_value_array = popup_reply_data.name_to_value_array;
var passthru_data = popup_reply_data.passthru_data;
// construct the POST request
var query_array = new Array();
if (name_to_value_array != 'undefined') {
for (var the_key in name_to_value_array)
{
if(the_key == 'toJSON')
{
/* just ignore */
}
else
{
query_array.push(the_key+"="+name_to_value_array[the_key]);
}
}
}
//construct the muulti select list
var selection_list = popup_reply_data.selection_list;
if (selection_list != 'undefined') {
for (var the_key in selection_list)
{
query_array.push('subpanel_id[]='+selection_list[the_key])
}
}
var module = get_module_name();
var id = get_record_id();
query_array.push('value=DetailView');
query_array.push('module='+module);
query_array.push('http_method=get');
query_array.push('return_module='+module);
query_array.push('return_id='+id);
query_array.push('record='+id);
query_array.push('isDuplicate=false');
query_array.push('action=Save2');
query_array.push('inline=1');
var refresh_page = escape(passthru_data['refresh_page']);
for (prop in passthru_data) {
if (prop=='link_field_name') {
query_array.push('subpanel_field_name='+escape(passthru_data[prop]));
} else {
if (prop=='module_name') {
query_array.push('subpanel_module_name='+escape(passthru_data[prop]));
} else {
query_array.push(prop+'='+escape(passthru_data[prop]));
}
}
}
var query_string = query_array.join('&');
request_map[request_id] = passthru_data['child_field'];
var returnstuff = http_fetch_sync('index.php',query_string);
request_id++;
got_data(returnstuff, true);
if(refresh_page == 1){
document.location.reload(true);
}
}
function got_data(args, inline)
{
var list_subpanel = document.getElementById('list_subpanel_'+request_map[args.request_id].toLowerCase());
//this function assumes that we are always working with a subpanel..
//add a null check to prevent failures when we are not.
if (list_subpanel != null) {
var subpanel = document.getElementById('subpanel_'+request_map[args.request_id].toLowerCase());
var child_field = request_map[args.request_id].toLowerCase();
if(inline){
//CCL - 21752
//if this is an inline operation, get the original buttons in the td element
//so that we may replace them later
buttonHTML = '';
trEls = list_subpanel.getElementsByTagName('tr');
if(trEls && trEls.length > 0) {
for(x in trEls) {
if(trEls[x] && trEls[x].className == 'pagination') {
tableEls = trEls[x].getElementsByTagName('table');
tdEls = tableEls[0].getElementsByTagName('td');
span = tdEls[0].getElementsByTagName('span');
if(span) {
buttonHTML = span[0].innerHTML;
}
break;
}
}
}
child_field_loaded[child_field] = 2;
list_subpanel.innerHTML='';
list_subpanel.innerHTML=args.responseText;
//now if the trPagination element is set then let's replace the new tr element with this
if(buttonHTML != '') {
list_subpanel = document.getElementById('list_subpanel_'+request_map[args.request_id].toLowerCase());
trEls = list_subpanel.getElementsByTagName('tr');
for(x in trEls) {
if(trEls[x] && trEls[x].className == 'pagination') {
tableEls = trEls[x].getElementsByTagName('table');
tdEls = tableEls[0].getElementsByTagName('td');
span = tdEls[0].getElementsByTagName('span');
span[0].innerHTML = buttonHTML;
break;
}
}
}
} else {
child_field_loaded[child_field] = 1;
subpanel.innerHTML='';
subpanel.innerHTML=args.responseText;
/* walk into the DOM and insert the list_subpanel_* div */
var inlineTable = subpanel.getElementsByTagName('table');
inlineTable = inlineTable[1];
inlineTable = subpanel.removeChild(inlineTable);
var listDiv = document.createElement('div');
listDiv.id = 'list_subpanel_'+request_map[args.request_id].toLowerCase();
subpanel.appendChild(listDiv);
listDiv.appendChild(inlineTable);
}
subpanel.style.display = '';
set_div_cookie(subpanel.cookie_name, '');
if (current_child_field != '' && child_field != current_child_field)
{
// commented out for now. this was originally used by tab UI of subpanels
//hideSubPanel(current_child_field);
}
current_child_field = child_field;
}
}
function showSubPanel(child_field,url,force_load,layout_def_key)
{
var inline = 1;
if ( typeof(force_load) == 'undefined' || force_load == null)
{
force_load = false;
}
if (force_load || typeof( child_field_loaded[child_field] ) == 'undefined')
{
request_map[request_id] = child_field;
if ( typeof (url) == 'undefined' || url == null)
{
var module = get_module_name();
var id = get_record_id();
if ( typeof(layout_def_key) == 'undefined' || layout_def_key == null ) {
layout_def_key = get_layout_def_key();
}
url = 'index.php?sugar_body_only=1&module='+module+'&subpanel='+child_field+'&action=SubPanelViewer&inline=' + inline + '&record='+id + '&layout_def_key='+ layout_def_key;
}
if ( url.indexOf('http://') != 0 && url.indexOf('https://') != 0)
{
url = ''+url ;
}
current_subpanel_url = url;
// http_fetch_async(url,got_data,request_id++);
var returnstuff = http_fetch_sync(url+ '&inline=' + inline + '&ajaxSubpanel=true');
request_id++;
got_data(returnstuff, inline);
}
else
{
var subpanel = document.getElementById('subpanel_'+child_field);
subpanel.style.display = '';
set_div_cookie(subpanel.cookie_name, '');
if (current_child_field != '' && child_field != current_child_field)
{
hideSubPanel(current_child_field);
}
current_child_field = child_field;
}
if(typeof(url) != 'undefined' && url != null && url.indexOf('refresh_page=1') > 0){
document.location.reload();
}
}
function markSubPanelLoaded(child_field){
child_field_loaded[child_field] = 2;
}
function hideSubPanel(child_field)
{
var subpanel = document.getElementById('subpanel_'+child_field);
subpanel.style.display = 'none';
set_div_cookie(subpanel.cookie_name, 'none');
}
var sub_cookie_name = get_module_name() + '_divs';
var temp = Get_Cookie(sub_cookie_name);
var div_cookies = new Array();
if(temp && typeof(temp) != 'undefined'){
div_cookies = get_sub_cookies(temp);
}
function set_div_cookie(name, display){
div_cookies[name] = display;
Set_Cookie(sub_cookie_name, subs_to_cookie(div_cookies), 3000, false, false,false);
}
function local_open_popup(name, width, height,arg1, arg2, arg3, params)
{
return open_popup(name, width, height,arg1,arg2,arg3, params);
}
SUGAR.subpanelUtils = function() {
var originalLayout = null;
var subpanelContents = {};
var subpanelLocked = {};
return {
// get the current subpanel layout
getLayout: function(asString, ignoreHidden) {
subpanels = document.getElementById('subpanel_list');
subpanelIds = new Array();
for(wp = 0; wp < subpanels.childNodes.length; wp++) {
if(typeof subpanels.childNodes[wp].id != 'undefined' && subpanels.childNodes[wp].id.match(/whole_subpanel_[\w-]*/) && (typeof ignoreHidden == 'undefined' || subpanels.childNodes[wp].style.display != 'none')) {
subpanelIds.push(subpanels.childNodes[wp].id.replace(/whole_subpanel_/,''));
}
}
if(asString) return subpanelIds.join(',');
else return subpanelIds;
},
// called when subpanel is picked up
onDrag: function(e, id) {
originalLayout = SUGAR.subpanelUtils.getLayout(true, true);
},
// called when subpanel is dropped
onDrop: function(e, id) {
newLayout = SUGAR.subpanelUtils.getLayout(true, true);
if(originalLayout != newLayout) { // only save if the layout has changed
SUGAR.subpanelUtils.saveLayout(newLayout);
}
},
// save the layout of the subpanels
saveLayout: function(order) {
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING_LAYOUT'));
if(typeof SUGAR.subpanelUtils.currentSubpanelGroup != 'undefined') {
var orderList = SUGAR.subpanelUtils.getLayout(false, true);
var currentGroup = SUGAR.subpanelUtils.currentSubpanelGroup;
}
var success = function(data) {
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVED_LAYOUT'));
window.setTimeout('ajaxStatus.hideStatus()', 2000);
if(typeof SUGAR.subpanelUtils.currentSubpanelGroup != 'undefined') {
SUGAR.subpanelUtils.reorderSubpanelSubtabs(currentGroup, orderList);
}
}
url = 'index.php?module=Home&action=SaveSubpanelLayout&layout=' + order + '&layoutModule=' + currentModule;
if(typeof SUGAR.subpanelUtils.currentSubpanelGroup != 'undefined') {
url = url + '&layoutGroup=' + encodeURI(SUGAR.subpanelUtils.currentSubpanelGroup);
}
var cObj = YAHOO.util.Connect.asyncRequest('GET', url, {success: success, failure: success});
},
// call when an inline create is saved
// buttonName is the id of the originating 'save' button - we determine the associated subpanel name by climbing the DOM from this point
// We require the subpanel name to refresh the subpanel contents and to close the subpanel after the save. However, the code the generates the button
// doesn't have access to the subpanel name, only the module name. Hence this rather long-winded mechanism.
inlineSave: function(theForm, buttonName) {
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING'));
var success = function(data) {
var element = document.getElementById(buttonName);
do {
element = element.parentNode;
} while ( element.className != 'quickcreate' && element.parentNode ) ;
if (element.className == 'quickcreate') {
var subpanel = element.id.slice(9,-7) ; // retrieve the subpanel name from the div id - the name is encoded as 'subpanel_<subpanelname>_newdiv'
SUGAR.subpanelUtils.cancelCreate(buttonName);
var module = get_module_name();
var id = get_record_id();
var layout_def_key = get_layout_def_key();
try {
eval('result = ' + data.responseText);
} catch (err) {
}
if (typeof(result) != 'undefined' && result != null && typeof(result['status']) != 'undefined' && result['status'] !=null && result['status'] == 'dupe') {
document.location.href = "index.php?" + result['get'].replace(/&amp;/gi,'&').replace(/&lt;/gi,'<').replace(/&gt;/gi,'>').replace(/&#039;/gi,'\'').replace(/&quot;/gi,'"').replace(/\r\n/gi,'\n');
return;
} else {
showSubPanel(subpanel, null, true);
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVED'));
window.setTimeout('ajaxStatus.hideStatus()', 1000);
if(reloadpage) window.location.reload(false);
}
}
}
// reload page if we are setting status to Held
var reloadpage = false;
if ((buttonName == 'Meetings_subpanel_save_button' || buttonName == 'Calls_subpanel_save_button' ) && document.getElementById(theForm).status[document.getElementById(theForm).status.selectedIndex].value == 'Held') {
reloadpage = true;
}
YAHOO.util.Connect.setForm(theForm, true, true);
var cObj = YAHOO.util.Connect.asyncRequest('POST', 'index.php', {success: success, failure: success, upload:success});
return false;
},
sendAndRetrieve: function(theForm, theDiv, loadingStr) {
function success(data) {
theDivObj = document.getElementById(theDiv);
subpanelContents[theDiv] = new Array();
subpanelContents[theDiv]['list'] = theDivObj;
subpanelContents[theDiv]['newDiv'] = document.createElement('div');
dataToDOMAvail = false;
subpanelContents[theDiv]['newDiv'].innerHTML = '<script type="text/javascript">dataToDOMAvail=true;</script>' + data.responseText; // fill the div
subpanelContents[theDiv]['newDiv'].id = theDiv + '_newDiv';
subpanelContents[theDiv]['newDiv'].className = 'quickcreate' ;
theDivObj.style.display = 'none';
theDivObj.parentNode.insertBefore(subpanelContents[theDiv]['newDiv'], theDivObj);
if (!dataToDOMAvail) {
SUGAR.util.evalScript(data.responseText);
}
subpanelLocked[theDiv] = false;
setTimeout("enableQS(false)",500);
ajaxStatus.hideStatus();
}
if(typeof subpanelLocked[theDiv] != 'undefined' && subpanelLocked[theDiv]) return false;
subpanelLocked[theDiv] = true;
if(typeof loadingStr == 'undefined') loadingStr = SUGAR.language.get('app_strings', 'LBL_LOADING');
ajaxStatus.showStatus(loadingStr);
YAHOO.util.Connect.setForm(theForm);
var cObj = YAHOO.util.Connect.asyncRequest('POST', 'index.php', {success: success, failure: success});
return false;
},
cancelCreate: function(buttonName) {
var element = document.getElementById(buttonName);
do {
element = element.parentNode;
} while ( element.className != 'quickcreate' && element.parentNode ) ;
var theDiv = element.id.substr(0,element.id.length-7);
if (typeof(subpanelContents[theDiv]) == 'undefined')
return false;
subpanelContents[theDiv]['newDiv'].parentNode.removeChild(subpanelContents[theDiv]['newDiv']);
subpanelContents[theDiv]['list'].style.display = '';
return false;
},
loadSubpanelGroupFromMore: function(group){
SUGAR.subpanelUtils.updateSubpanelMoreTab(group);
SUGAR.subpanelUtils.loadSubpanelGroup(group);
},
updateSubpanelMoreTab: function(group){
// Update Tab
var moreTab = document.getElementById(SUGAR.subpanelUtils.subpanelMoreTab + '_sp_tab');
moreTab.id = group + '_sp_tab';
moreTab.getElementsByTagName('a')[0].innerHTML = group;
moreTab.getElementsByTagName('a')[0].href = "javascript:SUGAR.subpanelUtils.loadSubpanelGroup('"+group+"');";
// Update Menu
var menuLink = document.getElementById(group+'_sp_mm');
menuLink.id = SUGAR.subpanelUtils.subpanelMoreTab+'_sp_mm';
menuLink.href = "javascript:SUGAR.subpanelUtils.loadSubpanelGroupFromMore('"+SUGAR.subpanelUtils.subpanelMoreTab+"');";
menuLink.innerHTML = SUGAR.subpanelUtils.subpanelMoreTab;
SUGAR.subpanelUtils.subpanelMoreTab = group;
},
/* loadSubpanels:
/* construct set of needed subpanels */
/* if we have not yet loaded this subpanel group, */
/* set loadedGroups[group] */
/* for each subpanel in subpanelGroups[group] */
/* if document.getElementById('whole_subpanel_'+subpanel) doesn't exist */
/* then add subpanel to set of needed subpanels */
/* if we need to load any subpanels, send a request for them */
/* with updateSubpanels as the callback. */
/* otherwise call updateSubpanels */
/* call setGroupCookie */
loadSubpanelGroup: function(group){
if(group == SUGAR.subpanelUtils.currentSubpanelGroup) return;
if(SUGAR.subpanelUtils.loadedGroups[group]){
SUGAR.subpanelUtils.updateSubpanel(group);
}else{
SUGAR.subpanelUtils.loadedGroups.push(group);
var needed = Array();
for(group_sp in SUGAR.subpanelUtils.subpanelGroups[group]){
if(typeof(SUGAR.subpanelUtils.subpanelGroups[group][group_sp]) == 'string' && !document.getElementById('whole_subpanel_'+SUGAR.subpanelUtils.subpanelGroups[group][group_sp])){
needed.push(SUGAR.subpanelUtils.subpanelGroups[group][group_sp]);
}
}
var success = function(){
SUGAR.subpanelUtils.updateSubpanelEventHandlers(needed);
SUGAR.subpanelUtils.updateSubpanels(group);
};
/* needed to retrieve each of the specified subpanels and install them ...*/
/* load them in bulk, insert via innerHTML, then sort nodes later. */
if(needed.length){
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_LOADING'));
SUGAR.util.retrieveAndFill(SUGAR.subpanelUtils.requestUrl + needed.join(','),'subpanel_list', null, success, null, true);
}else{
SUGAR.subpanelUtils.updateSubpanels(group);
}
}
SUGAR.subpanelUtils.setGroupCookie(group);
},
/* updateSubpanels:
/* for each child node of subpanel_list */
/* let subpanel name be id.match(/whole_subpanel_(\w*)/) */
/* if the subpanel name is in the list of subpanels for the current group, show it */
/* otherwise hide it */
/* swap nodes to suit user's order */
/* call updateSubpanelTabs */
updateSubpanels: function(group){
var sp_list = document.getElementById('subpanel_list');
for(sp in sp_list.childNodes){
if(sp_list.childNodes[sp].id){
sp_list.childNodes[sp].style.display = 'none';
}
}
for(group_sp in SUGAR.subpanelUtils.subpanelGroups[group]){
if ( typeof(SUGAR.subpanelUtils.subpanelGroups[group][group_sp]) != 'string' ) continue;
var cur = document.getElementById('whole_subpanel_'+SUGAR.subpanelUtils.subpanelGroups[group][group_sp]);
cur.style.display = 'block';
/* use YDD swapNodes this and first, second, etc. */
try{
YAHOO.util.DDM.swapNode(cur, sp_list.getElementsByTagName('LI')[group_sp]);
}catch(e){
}
}
SUGAR.subpanelUtils.updateSubpanelTabs(group);
},
updateSubpanelTabs: function(group){
if(SUGAR.subpanelUtils.showLinks){
SUGAR.subpanelUtils.updateSubpanelSubtabs(group);
document.getElementById('subpanelSubTabs').innerHTML = SUGAR.subpanelUtils.subpanelSubTabs[group];
}
oldTab = document.getElementById(SUGAR.subpanelUtils.currentSubpanelGroup+'_sp_tab');
if(oldTab){
oldTab.className = '';
oldTab.getElementsByTagName('a')[0].className = '';
}
mainTab = document.getElementById(group+'_sp_tab');
mainTab.className = 'active';
mainTab.getElementsByTagName('a')[0].className = 'current';
SUGAR.subpanelUtils.currentSubpanelGroup = group;
ajaxStatus.hideStatus();
},
updateSubpanelEventHandlers: function(){
if(SubpanelInitTabNames){
SubpanelInitTabNames(SUGAR.subpanelUtils.getLayout(false));
}
},
reorderSubpanelSubtabs: function(group, order){
SUGAR.subpanelUtils.subpanelGroups[group] = order;
if(SUGAR.subpanelUtils.showLinks==1){
SUGAR.subpanelUtils.updateSubpanelSubtabs(group);
if(SUGAR.subpanelUtils.currentSubpanelGroup == group){
document.getElementById('subpanelSubTabs').innerHTML = SUGAR.subpanelUtils.subpanelSubTabs[group];
}
}
},
// Re-renders the contents of subpanelSubTabs[group].
// Does not immediately affect what's on the screen.
updateSubpanelSubtabs: function(group){
var notFirst = 0;
var preMore = SUGAR.subpanelUtils.subpanelGroups[group].slice(0, SUGAR.subpanelUtils.subpanelMaxSubtabs);
SUGAR.subpanelUtils.subpanelSubTabs[group] = '<table border="0" cellpadding="0" cellspacing="0" height="20" width="100%" class="subTabs"><tr>';
for(var sp_key = 0; sp_key < preMore.length; sp_key++){
if(notFirst != 0){
SUGAR.subpanelUtils.subpanelSubTabs[group] += '<td width="1"> | </td>';
}else{
notFirst = 1;
}
SUGAR.subpanelUtils.subpanelSubTabs[group] += '<td nowrap="nowrap"><a href="#'+preMore[sp_key]+'" class="subTabLink">'+SUGAR.subpanelUtils.subpanelTitles[preMore[sp_key]]+'</a></td>';
}
if(document.getElementById('MoreSub'+group+'PanelMenu')){
SUGAR.subpanelUtils.subpanelSubTabs[group] += '<td nowrap="nowrap"> | &nbsp;<span class="subTabMore" id="MoreSub'+group+'PanelHandle" style="margin-left:2px; cursor: pointer; cursor: hand;" align="absmiddle" onmouseover="SUGAR.subpanelUtils.menu.tbspButtonMouseOver(this.id,\'\',\'\',0);">&gt;&gt;</span></td>';
}
SUGAR.subpanelUtils.subpanelSubTabs[group] += '<td width="100%">&nbsp;</td></tr></table>';
// Update the more menu for the current group
var postMore = SUGAR.subpanelUtils.subpanelGroups[group].slice(SUGAR.subpanelUtils.subpanelMaxSubtabs);
var subpanelMenu = document.getElementById('MoreSub'+group+'PanelMenu');
if(postMore && subpanelMenu){
subpanelMenu.innerHTML = '';
for(var sp_key = 0; sp_key < postMore.length; sp_key++){
subpanelMenu.innerHTML += '<a href="#'+postMore[sp_key]+'" class="menuItem" parentid="MoreSub'+group+'PanelMenu" onmouseover="hiliteItem(this,\'yes\'); closeSubMenus(this);" onmouseout="unhiliteItem(this);">'+SUGAR.subpanelUtils.subpanelTitles[postMore[sp_key]]+'</a>';
}
subpanelMenu += '</div>';
}
},
setGroupCookie: function(group){
Set_Cookie(SUGAR.subpanelUtils.tabCookieName, group, 3000, false, false,false);
}
};
}();
SUGAR.subpanelUtils.menu = function(){
return {
tbspButtonMouseOver : function(id,top,left,leftOffset){ //*//
closeMenusDelay = eraseTimeout(closeMenusDelay);
if (openMenusDelay == null){
openMenusDelay = window.setTimeout("SUGAR.subpanelUtils.menu.spShowMenu('"+id+"','"+top+"','"+left+"','"+leftOffset+"')", delayTime);
}
},
spShowMenu : function(id,top,left,leftOffset){ //*//
openMenusDelay = eraseTimeout(openMenusDelay);
var menuName = id.replace(/Handle/i,'Menu');
var menu = getLayer(menuName);
//if (menu) menu.className = 'tbButtonMouseOverUp';
if (currentMenu){
closeAllMenus();
}
SUGAR.subpanelUtils.menu.spPopupMenu(id, menu, top,left,leftOffset);
},
spPopupMenu : function(handleID, menu, top, left, leftOffset){ //*//
var bw = checkBrowserWidth();
var menuName = handleID.replace(/Handle/i,'Menu');
var menuWidth = 120;
var imgWidth = document.getElementById(handleID).width;
if (menu){
var menuHandle = getLayer(handleID);
var p=menuHandle;
if (left == "") {
var left = 0;
while(p&&p.tagName.toUpperCase()!='BODY'){
left+=p.offsetLeft;
p=p.offsetParent;
}
left+=parseInt(leftOffset);
}
if (top == "") {
var top = 0;
p=menuHandle;
top+=p.offsetHeight;
while(p&&p.tagName.toUpperCase()!='BODY'){
top+=p.offsetTop;
p=p.offsetParent;
}
}
if (left+menuWidth>bw) {
left = left-menuWidth+imgWidth;
}
setMenuVisible(menu, left, top, false);
}
}
};
}();

View File

@@ -0,0 +1,304 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
SUGAR.dependentDropdown = {
/*
* Container for "action" metadata - allows DD to parse saved choices and apply them at display time
*/
currentAction : null,
/*
* Flag to turn on debug mode.
* Current debug output:
* SUGAR.dependentDropdown._stack - simple list of this class' called methods
*/
debugMode : false
}
/**
* Handle drop-down dependencies
* @param object HTML form element object
*/
SUGAR.dependentDropdown.handleDependentDropdown = function(el) {
/**
*
*
* PROTOTYPE THIS METHOD TO CUSTOMIZE RESPONSES FOR YOUR DEPENDENT DROPDOWNS
*
*
*
*/
/**
if(SUGAR.dependentDropdown.debugMode) SUGAR.dependentDropdown.utils.debugStack('handleDependentDropdown');
/*
* el.id example:
* "criteriaGroup::0:::0:-:crit0id"
* [grouping from metadata]::[index]:::[elementIndex]:-:[assignedID from metadata]
* index is row-number
* elementIndex is the index of the current element in this row
var index = el.id.slice(el.id.indexOf("::") + 2, el.id.indexOf(":::"));
var elementRow = el.boxObject.parentBox;
var elementIndex = el.id.slice(el.id.indexOf(":::") + 3, el.id.indexOf(":-:"));
elementIndex++;
var elementKey = "element" + elementIndex;
var focusElement = SUGAR.dependentDropdown.dropdowns[focusDD].elements[elementKey];
if(focusElement) {
if(focusElement.handlers) {
try {
focusElement = focusElement.handlers[el.value];
} catch(e) {
if(SUGAR.dependentDropdown.dropdowns.debugMode) {
debugger;
}
}
}
SUGAR.dependentDropdown.generateElement(focusElement, elementRow, index, elementIndex);
} else {
}
*/
}
SUGAR.dependentDropdown.generateElement = function(focusElement, elementRow, index, elementIndex) {
if(SUGAR.dependentDropdown.debugMode) SUGAR.dependentDropdown.utils.debugStack('generateElement');
var tmp = null;
if(focusElement) {
/* get sandbox to play in */
var sandbox = SUGAR.dependentDropdown.utils.generateElementContainer(focusElement, elementRow, index, elementIndex);
/* handle labels that appear 'left' or 'top' */
if(focusElement.label) {
focusLabel = {
tag : 'span',
cls : 'routingLabel',
html : "&nbsp;" + focusElement.label + "&nbsp;"
}
switch(focusElement.label_pos) {
case "top":
focusLabel.html = focusElement.label + "<br />";
break;
case "bottom":
focusLabel.html = "<br />" + focusElement.label;
break;
}
if(focusElement.label_pos == 'left' || focusElement.label_pos == 'top') {
YAHOO.ext.DomHelper.append(sandbox, focusLabel);
}
}
/**********************************************************************
* FUN PART BELOW
*/
switch(focusElement.type) {
case 'input':
/*
* focusElement.values can be lazy-loaded via JS call
*/
if(typeof(focusElement.values) == 'string') {
focusElement.values = eval(focusElement.values);
}
/* Define the key-value that is to be used to pre-select a value in the dropdown */
var preselect = SUGAR.dependentDropdown.utils.getPreselectKey(focusElement.name);
if(preselect.match(/::/))
preselect = '';
tmp = YAHOO.ext.DomHelper.append(sandbox, {
tag : 'input',
id : focusElement.grouping + "::" + index + ":::" + elementIndex + ":-:" + focusElement.id,
name : focusElement.grouping + "::" + index + "::" + focusElement.name,
cls : 'input',
onchange : focusElement.onchange,
value : preselect
}, true);
var newElement = tmp.dom;
break;
case 'select':
tmp = YAHOO.ext.DomHelper.append(sandbox, {
tag : 'select',
id : focusElement.grouping + "::" + index + ":::" + elementIndex + ":-:" + focusElement.id,
name : focusElement.grouping + "::" + index + "::" + focusElement.name,
cls : 'input',
onchange : focusElement.onchange
}, true);
var newElement = tmp.dom;
/*
* focusElement.values can be lazy-loaded via JS call
*/
if(typeof(focusElement.values) == 'string') {
focusElement.values = eval(focusElement.values);
}
/* Define the key-value that is to be used to pre-select a value in the dropdown */
var preselect = SUGAR.dependentDropdown.utils.getPreselectKey(focusElement.name);
// Loop through the values (passed or generated) and preselect as needed
var i = 0;
for(var key in focusElement.values) {
var selected = (preselect == key) ? true : false;
newElement.options[i] = new Option(focusElement.values[key], key, selected);
// ie6/7 workaround
if(selected) {
newElement.options[i].selected = true;
}
i++;
}
break;
case 'none':
break;
case 'checkbox':
alert('implement checkbox pls');
break;
case 'multiple':
alert('implement multiple pls');
break;
default:
if(SUGAR.dependentDropdown.dropdowns.debugMode) {
alert("Improper type defined: [ " + focusElement.type + "]");
}
return;
break;
}
/* handle label placement *after* or *below* the drop-down */
if(focusElement.label) {
if(focusElement.label_pos == 'right' || focusElement.label_pos == 'bottom') {
YAHOO.ext.DomHelper.append(sandbox, focusLabel);
}
}
/* trigger dependent dropdown action to cascade dependencies */
try {
newElement.onchange();
//eval(focusElement.onchange); "this" has no reference
} catch(e) {
if(SUGAR.dependentDropdown.dropdowns.debugMode) {
debugger;
}
}
} else {
}
}
///////////////////////////////////////////////////////////////////////////////
//// UTILS
SUGAR.dependentDropdown.utils = {
/**
* creates a DIV container for a given element
* @param object focusElement Element in focus' metadata
* @param object elementRow Parent DIV container's DOM object
* @param int index Index of current elementRow
* @param int elementIndex Index of the element in focus relative to others in the definition
* @return obj Reference DOM object generated
*/
generateElementContainer : function(focusElement, elementRow, index, elementIndex) {
/* clear out existing element if exists */
var oldElement = document.getElementById('elementContainer' + focusElement.grouping + "::" + index + ":::" + elementIndex);
if(oldElement) {
SUGAR.dependentDropdown.utils.removeChildren(oldElement);
}
/* create sandbox to ease removal */
var tmp = YAHOO.ext.DomHelper.append(elementRow, {
tag : 'span',
id : 'elementContainer' + focusElement.grouping + "::" + index + ":::" + elementIndex
}, true);
return tmp.dom;
},
/**
* Finds the preselect key from the User's saved (loaded into memory) metadata
* @param string elementName Name of form element - functions as key to user's saved value
*/
getPreselectKey : function(elementName) {
try {
if(SUGAR.dependentDropdown.currentAction.action[elementName]) {
return SUGAR.dependentDropdown.currentAction.action[elementName];
} else {
return '';
}
} catch(e) {
if(SUGAR.dependentDropdown.dropdowns.debugMode) {
//debugger;
}
return '';
}
},
/**
* provides a list of methods called in order when debugging
* @param object
*/
debugStack : function(func) {
if(!SUGAR.dependentDropdown._stack) {
SUGAR.dependentDropdown._stack = new Array();
}
SUGAR.dependentDropdown._stack.push(func);
},
/**
* Removes all child nodes from the passed DOM element
*/
removeChildren : function(el) {
for(i=el.childNodes.length - 1; i >= 0; i--) {
if(el.childNodes[i]) {
el.removeChild(el.childNodes[i]);
}
}
}
}

View File

@@ -0,0 +1,487 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
(function() {
//Do not double define
if (SUGAR.EmailAddressWidget) return;
var Dom = YAHOO.util.Dom;
SUGAR.EmailAddressWidget = function(module) {
if (!SUGAR.EmailAddressWidget.count[module]) SUGAR.EmailAddressWidget.count[module] = 0;
this.count = SUGAR.EmailAddressWidget.count[module];
SUGAR.EmailAddressWidget.count[module]++;
this.module = module;
this.id = this.module + this.count;
if (document.getElementById(module+'_email_widget_id'))
document.getElementById(module+'_email_widget_id').value = this.id;
SUGAR.EmailAddressWidget.instances[this.id] = this;
}
SUGAR.EmailAddressWidget.instances = {};
SUGAR.EmailAddressWidget.count = {};
SUGAR.EmailAddressWidget.prototype = {
emailTemplate : '<tr id="emailAddressRow">' +
'<td nowrap="NOWRAP"><input type="text" name="emailAddress{$index}" id="emailAddress0" size="30"/></td>' +
'<td><span>&nbsp;</span><img id="removeButton0" name="0" src="index.php?entryPoint=getImage&amp;themeName=Sugar&amp;imageName=delete_inline.gif"/></td>' +
'<td align="center"><input type="radio" name="emailAddressPrimaryFlag" id="emailAddressPrimaryFlag0" value="emailAddress0" enabled="true" checked="true"/></td>' +
'<td align="center"><input type="checkbox" name="emailAddressOptOutFlag[]" id="emailAddressOptOutFlag0" value="emailAddress0" enabled="true"/></td>' +
'<td align="center"><input type="checkbox" name="emailAddressInvalidFlag[]" id="emailAddressInvalidFlag0" value="emailAddress0" enabled="true"/></td>' +
'<td><input type="hidden" name="emailAddressVerifiedFlag0" id="emailAddressVerifiedFlag0" value="true"/></td>' +
'<td><input type="hidden" name="emailAddressVerifiedValue0" id="emailAddressVerifiedValue0" value=""/></td></tr>',
numberEmailAddresses : 0,
replyToFlagObject : new Object(),
verifying : false,
enterPressed : false,
tabPressed : false,
emailView:"",
emailIsRequired: false,
prefillEmailAddresses: function(tableId, o){
for (i = 0; i < o.length; i++) {
o[i].email_address = o[i].email_address.replace('&#039;', "'");
this.addEmailAddress(tableId, o[i].email_address, o[i].primary_address, o[i].reply_to_address, o[i].opt_out, o[i].invalid_email);
}
},
retrieveEmailAddress: function (event) {
var callbackFunction = function success(data) {
var vals = YAHOO.lang.JSON.parse(data.responseText);
var target = vals.target;
event = this.getEvent(event);
if(vals.email) {
var email = vals.email;
if(email != '' && /\d+$/.test(target)) {
var matches = target.match(/\d+$/);
var targetNumber = matches[0];
var optOutEl = Dom.get(this.id + 'emailAddressOptOutFlag' + targetNumber);
if(optOutEl) {
optOutEl.checked = email['opt_out'] == 1 ? true : false;
}
var invalidEl = Dom.get(this.id + 'emailAddressInvalidFlag' + targetNumber);
if(invalidEl) {
invalidEl.checked = email['invalid_email'] == 1 ? true : false;
}
}
}
//Set the verified flag to true
var index = /[a-z]*\d?emailAddress(\d+)/i.exec(target)[1];
var verifyElementFlag = Dom.get(this.id + 'emailAddressVerifiedFlag' + index);
if(verifyElementFlag.parentNode.childNodes.length > 1) {
verifyElementFlag.parentNode.removeChild(verifyElementFlag.parentNode.lastChild);
}
var verifiedTextNode = document.createElement('span');
verifiedTextNode.innerHTML = '';
verifyElementFlag.parentNode.appendChild(verifiedTextNode);
verifyElementFlag.value = "true";
this.verifyElementValue = Dom.get(this.id +'emailAddressVerifiedValue' + index);
this.verifyElementValue.value = Dom.get(this.id +'emailAddress' + index).value;
this.verifying = false;
// If Enter key or Save button was pressed then we proceed to attempt a form submission
var savePressed = false;
if(event) {
var elm = document.activeElement || event.explicitOriginalTarget;
if(typeof elm.type != 'undefined' && /submit|button/.test(elm.type.toLowerCase())) {
savePressed = true;
}
}
if(savePressed || this.enterPressed) {
setTimeout("SUGAR.EmailAddressWidget.instances." + this.id + ".forceSubmit()", 2100);
} else if(this.tabPressed) {
Dom.get(this.id + 'emailAddressPrimaryFlag' + index).focus();
}
}
var event = this.getEvent(event);
var targetEl = this.getEventElement(event);
var index = /[a-z]*\d?emailAddress(\d+)/i.exec(targetEl.id)[1];
var verifyElementFlag = Dom.get(this.id + 'emailAddressVerifiedFlag' + index);
this.verifyElementValue = Dom.get(this.id + 'emailAddressVerifiedValue' + index);
verifyElementFlag.value = (trim(targetEl.value) == '' || targetEl.value == this.verifyElementValue.value) ? "true" : "false"
//Remove the span element if it is present
if(verifyElementFlag.parentNode.childNodes.length > 1) {
verifyElementFlag.parentNode.removeChild(verifyElementFlag.parentNode.lastChild);
}
if(/emailAddress\d+$/.test(targetEl.id) && isValidEmail(targetEl.value) && !this.verifying && verifyElementFlag.value == "false") {
verifiedTextNode = document.createElement('span');
verifyElementFlag.parentNode.appendChild(verifiedTextNode);
verifiedTextNode.innerHTML = SUGAR.language.get('app_strings', 'LBL_VERIFY_EMAIL_ADDRESS');
this.verifying = true;
var cObj = YAHOO.util.Connect.asyncRequest(
'GET',
'index.php?&module=Contacts&action=RetrieveEmail&target=' + targetEl.id + '&email=' + targetEl.value,
{success: callbackFunction, failure: callbackFunction, scope: this}
);
}
},
handleKeyDown: function (event) {
var e = this.getEvent(event);
var eL = this.getEventElement(e);
if ((kc = e["keyCode"])) {
this.enterPressed = (kc == 13) ? true : false;
this.tabPressed = (kc == 9) ? true : false;
if(this.enterPressed || this.tabPressed) {
this.retrieveEmailAddress(e);
if (this.enterPressed);
this.freezeEvent(e);
}
}
}, //handleKeyDown()
getEvent :function (event) {
return (event ? event : window.event);
},//getEvent
getEventElement : function (e) {
return (e.srcElement ? e.srcElement: (e.target ? e.target : e.currentTarget));
},//getEventElement
freezeEvent : function (e) {
if (e.preventDefault) e.preventDefault();
e.returnValue = false;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return false;
},//freezeEvent
addEmailAddress : function (tableId, address, primaryFlag, replyToFlag, optOutFlag, invalidFlag) {
if (this.addInProgress)
return;
this.addInProgress = true;
if (!address)
address = "";
var insertInto = Dom.get(tableId);
var parentObj = insertInto.parentNode;
var newContent = document.createElement("input");
var nav = new String(navigator.appVersion);
var newContentPrimaryFlag;
if(SUGAR.isIE){
newContentPrimaryFlag = document.createElement("<input name='emailAddressPrimaryFlag' />");
}else{
newContentPrimaryFlag = document.createElement("input");
}
var newContentReplyToFlag = document.createElement("input");
var newContentOptOutFlag = document.createElement("input");
var newContentInvalidFlag = document.createElement("input");
var newContentVerifiedFlag = document.createElement("input");
var newContentVerifiedValue = document.createElement("input");
var removeButton = document.createElement("img");
var tbody = document.createElement("tbody");
var tr = document.createElement("tr");
var td1 = document.createElement("td");
var td2 = document.createElement("td");
var td3 = document.createElement("td");
var td4 = document.createElement("td");
var td5 = document.createElement("td");
var td6 = document.createElement("td");
var td7 = document.createElement("td");
var td8 = document.createElement("td");
// set input field attributes
newContent.setAttribute("type", "text");
newContent.setAttribute("name", this.id + "emailAddress" + this.numberEmailAddresses);
newContent.setAttribute("id", this.id + "emailAddress" + this.numberEmailAddresses);
newContent.setAttribute("size", "30");
if(address != '') {
newContent.setAttribute("value", address);
}
// remove button
removeButton.setAttribute("id", this.id + "removeButton" + this.numberEmailAddresses);
removeButton.setAttribute("class", "id-ff-remove");
removeButton.setAttribute("name", this.numberEmailAddresses);
removeButton.eaw = this;
removeButton.setAttribute("src", "index.php?entryPoint=getImage&themeName="+SUGAR.themes.theme_name+"&imageName=id-ff-remove.png");
removeButton.onclick = function(){this.eaw.removeEmailAddress(this.name);};
// set primary flag
newContentPrimaryFlag.setAttribute("type", "radio");
newContentPrimaryFlag.setAttribute("name", this.id + "emailAddressPrimaryFlag");
newContentPrimaryFlag.setAttribute("id", this.id + "emailAddressPrimaryFlag" + this.numberEmailAddresses);
newContentPrimaryFlag.setAttribute("value", this.id + "emailAddress" + this.numberEmailAddresses);
newContentPrimaryFlag.setAttribute("enabled", "true");
// set reply-to flag
newContentReplyToFlag.setAttribute("type", "radio");
newContentReplyToFlag.setAttribute("name", this.id + "emailAddressReplyToFlag");
newContentReplyToFlag.setAttribute("id", this.id + "emailAddressReplyToFlag" + this.numberEmailAddresses);
newContentReplyToFlag.setAttribute("value", this.id + "emailAddress" + this.numberEmailAddresses);
newContentReplyToFlag.setAttribute("enabled", "true");
newContentReplyToFlag.eaw = this;
newContentReplyToFlag['onclick']= function() {
var form = document.forms[this.eaw.emailView];
if (!form) {
form = document.forms['editContactForm'];
}
var nav = new String(navigator.appVersion);
if(nav.match(/MSIE/gim)) {
for(i=0; i<form.elements.length; i++) {
var id = new String(form.elements[i].id);
if(id.match(/emailAddressReplyToFlag/gim) && form.elements[i].type == 'radio' && id != this.eaw.id) {
form.elements[i].checked = false;
}
}
}
for(i=0; i<form.elements.length; i++) {
var id = new String(form.elements[i].id);
if(id.match(/emailAddressReplyToFlag/gim) && form.elements[i].type == 'radio' && id != this.eaw.id) {
this.eaw.replyToFlagObject[this.eaw.id] = false;
}
} // for
if (this.eaw.replyToFlagObject[this.id]) {
this.eaw.replyToFlagObject[this.id] = false;
this.checked = false;
} else {
this.eaw.replyToFlagObject[this.id] = true;
this.checked = true;
} // else
}
// set opt-out flag
newContentOptOutFlag.setAttribute("type", "checkbox");
newContentOptOutFlag.setAttribute("name", this.id + "emailAddressOptOutFlag[]");
newContentOptOutFlag.setAttribute("id", this.id + "emailAddressOptOutFlag" + this.numberEmailAddresses);
newContentOptOutFlag.setAttribute("value", this.id + "emailAddress" + this.numberEmailAddresses);
newContentOptOutFlag.setAttribute("enabled", "true");
newContentOptOutFlag.eaw = this;
newContentOptOutFlag['onClick'] = function(){this.eaw.toggleCheckbox(this)};
// set invalid flag
newContentInvalidFlag.setAttribute("type", "checkbox");
newContentInvalidFlag.setAttribute("name", this.id + "emailAddressInvalidFlag[]");
newContentInvalidFlag.setAttribute("id", this.id + "emailAddressInvalidFlag" + this.numberEmailAddresses);
newContentInvalidFlag.setAttribute("value", this.id + "emailAddress" + this.numberEmailAddresses);
newContentInvalidFlag.setAttribute("enabled", "true");
newContentInvalidFlag.eaw = this;
newContentInvalidFlag['onClick']= function(){this.eaw.toggleCheckbox(this)};
// set the verified flag and verified email value
newContentVerifiedFlag.setAttribute("type", "hidden");
newContentVerifiedFlag.setAttribute("name", this.id + "emailAddressVerifiedFlag" + this.numberEmailAddresses);
newContentVerifiedFlag.setAttribute("id", this.id + "emailAddressVerifiedFlag" + this.numberEmailAddresses);
newContentVerifiedFlag.setAttribute("value", "true");
newContentVerifiedValue.setAttribute("type", "hidden");
newContentVerifiedValue.setAttribute("name", this.id + "emailAddressVerifiedValue" + this.numberEmailAddresses);
newContentVerifiedValue.setAttribute("id", this.id + "emailAddressVerifiedValue" + this.numberEmailAddresses);
newContentVerifiedValue.setAttribute("value", address);
//Add to validation
this.emailView = (this.emailView == '') ? 'EditView' : this.emailView;
addToValidateVerified(this.emailView, this.id + "emailAddressVerifiedFlag" + this.numberEmailAddresses, 'bool', false, SUGAR.language.get('app_strings', 'LBL_VERIFY_EMAIL_ADDRESS'));
tr.setAttribute("id", this.id + "emailAddressRow" + this.numberEmailAddresses);
td1.setAttribute("nowrap", "NOWRAP");
td3.setAttribute("align", "center");
td4.setAttribute("align", "center");
td5.setAttribute("align", "center");
td6.setAttribute("align", "center");
td1.appendChild(newContent);
td1.appendChild(document.createTextNode(" "));
spanNode = document.createElement('span');
spanNode.innerHTML = '&nbsp;';
td2.appendChild(spanNode);
if (this.numberEmailAddresses != 0 || typeof (this.emailIsRequired) == "undefined" || !this.emailIsRequired)
td2.appendChild(removeButton);
td3.appendChild(newContentPrimaryFlag);
td4.appendChild(newContentReplyToFlag);
td5.appendChild(newContentOptOutFlag);
td6.appendChild(newContentInvalidFlag);
td7.appendChild(newContentVerifiedFlag);
td8.appendChild(newContentVerifiedValue);
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
if(typeof(this.module) != 'undefined' && this.module == 'Users') {
tr.appendChild(td4);
} else {
tr.appendChild(td5);
tr.appendChild(td6);
}
tr.appendChild(td7);
tr.appendChild(td8);
tbody.appendChild(tr);
insertInto.appendChild(tbody);
// insert the new div->input into the DOM
parentObj.insertBefore(Dom.get('targetBody'), insertInto);
// CL Fix for 17651 (added OR condition check to see if this is the first email added)
if(primaryFlag == '1' || (this.numberEmailAddresses == 0)) {
newContentPrimaryFlag.setAttribute("checked", 'true');
}
if(replyToFlag == '1') {
newContentReplyToFlag.setAttribute("checked", "true");
}
if (replyToFlag == '1') {
this.replyToFlagObject[newContentReplyToFlag.id] = true;
} else {
this.replyToFlagObject[newContentReplyToFlag.id] = false;
}
if(optOutFlag == '1') {
newContentOptOutFlag.setAttribute("checked", 'true');
}
if(invalidFlag == '1') {
newContentInvalidFlag.setAttribute("checked", "true");
}
newContent.eaw = this;
newContent.onblur = function(e){this.eaw.retrieveEmailAddress(e)};
newContent.onkeydown = function(e){this.eaw.handleKeyDown(e)};
// Add validation to field
addToValidate(this.emailView, this.id + 'emailAddress' + this.numberEmailAddresses, 'email', this.emailIsRequired, SUGAR.language.get('app_strings', 'LBL_EMAIL_ADDRESS_BOOK_EMAIL_ADDR'));
this.numberEmailAddresses++;
this.addInProgress = false;
}, //addEmailAddress
removeEmailAddress : function(index) {
removeFromValidate(this.emailView, this.id + 'emailAddress' + index);
var oNodeToRemove = Dom.get(this.id + 'emailAddressRow' + index);
oNodeToRemove.parentNode.removeChild(oNodeToRemove);
var removedIndex = parseInt(index);
//If we are not deleting the last email address, we need to shift the numbering to fill the gap
if(this.numberEmailAddresses != removedIndex) {
for(var x = removedIndex + 1; x < this.numberEmailAddresses; x++) {
Dom.get(this.id + 'emailAddress' + x).setAttribute("name", this.id +"emailAddress" + (x-1));
Dom.get(this.id + 'emailAddress' + x).setAttribute("id", this.id +"emailAddress" + (x-1));
if(Dom.get(this.id + 'emailAddressInvalidFlag' + x)) {
Dom.get(this.id + 'emailAddressInvalidFlag' + x).setAttribute("id", this.id + "emailAddressInvalidFlag" + (x-1));
}
if(Dom.get(this.id + 'emailAddressOptOutFlag' + x)){
Dom.get(this.id + 'emailAddressOptOutFlag' + x).setAttribute("id", this.id + "emailAddressOptOutFlag" + (x-1));
}
if(Dom.get(this.id + 'emailAddressPrimaryFlag' + x)) {
Dom.get(this.id + 'emailAddressPrimaryFlag' + x).setAttribute("id", this.id + "emailAddressPrimaryFlag" + (x-1));
}
Dom.get(this.id + 'emailAddressVerifiedValue' + x).setAttribute("id", this.id + "emailAddressVerifiedValue" + (x-1));
Dom.get(this.id + 'emailAddressVerifiedFlag' + x).setAttribute("id", this.id + "emailAddressVerifiedFlag" + (x-1));
var rButton = Dom.get(this.id + 'removeButton' + x);
rButton.setAttribute("name", (x-1));
rButton.setAttribute("id", this.id + "removeButton" + (x-1));
Dom.get(this.id + 'emailAddressRow' + x).setAttribute("id", this.id + 'emailAddressRow' + (x-1));
}
}
this.numberEmailAddresses--;
// CL Fix for 17651
if(this.numberEmailAddresses == 0) {
return;
}
var primaryFound = false;
for(x=0; x < this.numberEmailAddresses; x++) {
if(Dom.get(this.id + 'emailAddressPrimaryFlag' + x).checked) {
primaryFound = true;
}
}
if(!primaryFound) {
Dom.get(this.id + 'emailAddressPrimaryFlag0').checked = true;
Dom.get(this.id + 'emailAddressPrimaryFlag0').value = this.id + 'emailAddress0';
}
},
toggleCheckbox : function (el)
{
var form = document.forms[this.emailView];
if (!form) {
form = document.forms['editContactForm'];
}
if(SUGAR.isIE) {
for(i=0; i<form.elements.length; i++) {
var id = new String(form.elements[i].id);
if(id.match(/emailAddressInvalidFlag/gim) && form.elements[i].type == 'checkbox' && id != el.id) {
form.elements[i].checked = false;
}
}
el.checked = true;
}
},
forceSubmit : function () {
var theForm = Dom.get(this.emailView);
if(theForm) {
theForm.action.value = 'Save';
if(!check_form(this.emailView)) {
return false;
}
if(this.emailView == 'EditView') {
theForm.submit();
} else if(this.emailView == 'QuickCreate') {
SUGAR.subpanelUtils.inlineSave(theForm.id, theForm.module.value.toLowerCase());
}
}
} //forceSubmit
};
emailAddressWidgetLoaded = true;
})();

View File

@@ -0,0 +1,101 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
var elems = new Array("address_street", "address_city", "address_state", "address_postalcode", "address_country");
var tHasText = false;
var originalBgColor = '#FFFFFF';
var Dom = YAHOO.util.Dom;
function TestCheckboxReady(id) {
YAHOO.util.Event.onAvailable(id, this.handleOnAvailable, this);
}
TestCheckboxReady.prototype.handleOnAvailable = function(me) {
for(x in elems) {
f = fromKey + "_" + elems[x];
t = toKey + "_" + elems[x];
e1 = document.getElementById(t);
e2 = document.getElementById(f);
if(e1 != null && typeof e1 != "undefined" && e2 != null && typeof e2 != "undefined") {
if(!tHasText && trim(e1.value) != "") {
tHasText = true;
}
if(e1.value != e2.value) {
document.getElementById(this.id).checked = false;
break;
}
originalBgColor = e1.style.backgroundColor;
}
}
if(!tHasText) {
document.getElementById(this.id).checked = false;
} else {
syncFields(fromKey, toKey);
}
}
function writeToSyncField(e) {
fromEl = YAHOO.util.Event.getTarget(e, true);
if(typeof fromEl != "undefined") {
toEl = document.getElementById(fromEl.id.replace(fromKey, toKey));
toEl.value = fromEl.value;
}
}
function syncFields(fromKey, toKey) {
for(x in elems) {
f = fromKey + "_" + elems[x];
e2 = document.getElementById(f);
t = toKey + "_" + elems[x];
e1 = document.getElementById(t);
if(e1 != null && typeof e1 != "undefined" && e2 != null && typeof e2 != "undefined") {
if(!document.getElementById(toKey + '_checkbox').checked) {
Dom.setStyle(e1,'backgroundColor',originalBgColor);
e1.removeAttribute('readOnly');
YAHOO.util.Event.removeListener(e2, 'keyup');
} else {
e1.value = e2.value;
Dom.setStyle(e1,'backgroundColor','#DCDCDC');
e1.setAttribute('readOnly', true);
YAHOO.util.Event.addListener(e2, 'keyup', writeToSyncField);
}
}
} //for
}

View File

@@ -0,0 +1,589 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
if(typeof(SUGAR.collection) == "undefined") {
SUGAR.collection = function(form_name, field_name, module, popupData){
/*
* boolean variable to handle expand/collapse views
* false if the collection field is collapsed and true if the rows are expanded.
*/
this.more_status = false;
/*
* Store the form name containing this field. Example: EditView
*/
this.form = form_name;
/*
* Store the name of the collection field. Example: account_name
*/
this.field = field_name;
/*
* Store the unique form + field name that uses the combination of form and field
*/
this.field_element_name = this.form + '_' + this.field;
/*
* Store the name of the module from where come the field. Example: Accounts
*/
this.module = module;
/*
* Number of secondaries linked records (total of linked records - 1).
*/
this.fields_count = 0;
/*
* Number of extra fields.
*/
this.extra_fields_count = 0;
/*
* Set to true if it is the initialization.
*/
this.first = true;
/*
* Name of the primary field. Example: "accounts_collection_0"
*/
this.primary_field = "";
/*
* Store the row cloned in key "0" and the context cloned in key "1".
*/
this.cloneField = new Array();
/*
* Store the sqs_objects for the cloned row encoded in JSON.
*/
this.sqs_clone = "";
/*
* Store the name and the id of all the secondaries linked records. this is used to create the secondary rows.
*/
this.secondaries_values = new Array();
/*
* Store all the extra fields which has been updated in the collection field to save on save of the main record.
*/
this.update_fields = new Object();
/*
* boolean variable indicating whether or not to show the expand/collapse arrow
*/
this.show_more_image = true;
};
SUGAR.collection.prototype = {
/*
* Remove the row designated by the passed 'id' or clear the row if there is only one row.
*/
remove: function(num){
// if there is only one record, clear it instead of removing it
// this is determined by the visibility of the drop down arrow element
radio_els = this.get_radios();
if(radio_els.length == 1) {
div_el = document.getElementById(this.field_element_name + '_input_div_' + num);
input_els = div_el.getElementsByTagName('input');
//Clear text field
input_els[0].value = '';
//Clear hidden field
input_els[1].value = '';
if(this.primary_field) {
div_el = document.getElementById(this.field_element_name + '_radio_div_' + num);
radio_els = div_el.getElementsByTagName('input');
//Clear the radio field
radio_els[0].checked = false;
}
} else {
div_el = document.getElementById(this.field_element_name + '_input_div_' + num);
tr_to_remove = document.getElementById('lineFields_' + this.field_element_name + '_' + num);
div_el.parentNode.parentNode.parentNode.removeChild(tr_to_remove);
var radios = this.get_radios();
div_id = 'lineFields_' + this.field_element_name + '_' + num;
if (typeof sqs_objects[div_id.replace("_field_", "_")] != 'undefined') {
delete (sqs_objects[div_id.replace("_field_", "_")]);
}
var checked=false;
for(var k=0; k< radios.length; k++){
if(radios[k].checked){
checked=true;
}
}
// If we remove an entry marked as the primary, set another record as the primary
var primary_checked = document.forms[this.form].elements[this.field+"_allowed_to_check"];
var allowed_to_check = true;
if(primary_checked && primary_checked.value == 'false'){
allowed_to_check = false;
}
if(/EditView/.test(this.form) && !checked && typeof radios[0] != 'undefined' && allowed_to_check) {
radios[0].checked = true;
this.changePrimary(true);
this.js_more();
this.js_more();
}
// if there is now only one record, hide the "more..." link
if(radios.length == 1){
this.more_status = false;
document.getElementById('more_'+this.field_element_name).style.display='none';
this.show_arrow_label(false);
this.js_more();
}else{
this.js_more();
this.js_more();
}
}
},
get_radios: function() {
return YAHOO.util.Selector.query('input[name^=primary]', document.getElementById(this.field_element_name+'_table'));
},
/*
* Add a new empty row.
*/
add: function(values){
this.fields_count++;
var Field0 = this.init_clone(values);
this.cloneField[1].appendChild(Field0);
//Enable quicksearch for this field
enableQS(true);
this.changePrimary(false);
//If the arrow field and label are collapsed, un-collapse it
if(document.getElementById('more_'+this.field_element_name) && document.getElementById('more_'+this.field_element_name).style.display == 'none'){
document.getElementById('more_'+this.field_element_name).style.display='';
}
if(!this.is_expanded()) {
this.js_more();
this.show_arrow_label(true);
}
},
/*
* Add the secondaries rows on load of the page.
*/
add_secondaries: function(){
clone_id = this.form + '_' + this.field + '_collection_0';
if(typeof sqs_objects == 'undefined' || typeof sqs_objects[clone_id] == 'undefined') {
setTimeout('collection["'+this.field_element_name+'"].add_secondaries();',1000);
} else if(typeof document.getElementById(this.form + '_' + this.field + '_collection_0') == 'undefined'){
setTimeout('collection["'+this.field_element_name+'"].add_secondaries();',1000);
} else {
if(!this.create_clone())return;
enableQS();
this.changePrimary(true);
for(key in this.secondaries_values){
if (isInteger(key)) {
this.add(this.secondaries_values[key]);
}
}
this.js_more();
this.js_more();
}
},
/*
* Create the new row from a cloned row.
*/
init_clone: function(values){
//Safety check, this means that the clone field was not created yet
if(typeof this.cloneField[0] == 'undefined') {
return;
}
if (typeof values == "undefined") {
values = new Array();
values['name'] = "";
values['id'] = "";
}
var count = this.fields_count;
//Clone the table element containing the fields for each row
Field0 = this.cloneField[0].cloneNode(true);
Field0.id = "lineFields_"+this.field_element_name+"_"+count;
for ( var ii = 0; ii < Field0.childNodes.length; ii++ ){
if(typeof(Field0.childNodes[ii].tagName) != 'undefined' && Field0.childNodes[ii].tagName == "TD") {
for (var jj = 0; jj < Field0.childNodes[ii].childNodes.length; jj++) {
currentNode = Field0.childNodes[ii].childNodes[jj];
this.process_node(Field0.childNodes[ii], currentNode, values);
} //for
} //if
} //for
return Field0;
},
/**
* process_node
*
* method to process cloning of nodes, moved out of init_clone so that
* this may be recursively called
*/
process_node: function(parentNode, currentNode, values) {
if(parentNode.className == 'td_extra_field'){
// If this is an extra field
if(parentNode.id){
parentNode.id='';
}
var toreplace = this.field + "_collection_extra_0";
var re = new RegExp(toreplace, 'g');
parentNode.innerHTML = parentNode.innerHTML.replace(re, this.field + "_collection_extra_" + this.fields_count);
} else if (currentNode.tagName && currentNode.tagName == 'SPAN') {
//If it is our div element, recursively find all input elements to process
currentNode.id = /_input/.test(currentNode.id) ? this.field_element_name + '_input_div_' + this.fields_count : this.field_element_name + '_radio_div_' + this.fields_count;
input_els = currentNode.getElementsByTagName('input');
for(x in input_els) {
if(input_els[x].tagName && input_els[x].tagName == 'INPUT') {
this.process_node(parentNode, input_els[x], values);
}
}
} else if (currentNode.name) {
// If this is a standard field
var toreplace = this.field + "_collection_0";
var re = new RegExp(toreplace, 'g');
var name = currentNode.name;
var new_name = name.replace(re, this.field + "_collection_" + this.fields_count);
switch (name) {
case toreplace:
sqs_id = this.form + '_' + new_name;
if (typeof this.sqs_clone != 'undefined') {
var sqs_clone = YAHOO.lang.JSON.stringify(this.sqs_clone);
eval('sqs_objects[sqs_id]=' + sqs_clone);
for (var pop_field in sqs_objects[sqs_id]['populate_list']) {
if (typeof sqs_objects[sqs_id]['populate_list'][pop_field] == 'string') {
sqs_objects[sqs_id]['populate_list'][pop_field] = sqs_objects[sqs_id]['populate_list'][pop_field].replace(RegExp('_0', 'g'), "_" + this.fields_count);
}
}
for (var req_field in sqs_objects[sqs_id]['required_list']) {
if (typeof sqs_objects[sqs_id]['required_list'][req_field] == 'string') {
sqs_objects[sqs_id]['required_list'][req_field] = sqs_objects[sqs_id]['required_list'][req_field].replace(RegExp('_0', 'g'), "_" + this.fields_count);
}
}
}
currentNode.name = new_name;
currentNode.id = new_name;
currentNode.value = values['name'];
break;
case "id_" + toreplace:
currentNode.name = new_name.replace(RegExp('_0', 'g'), "_" + this.fields_count);
currentNode.id = new_name.replace(RegExp('_0', 'g'), "_" + this.fields_count);
currentNode.value = values['id'];
break;
case "btn_" + toreplace:
currentNode.name = new_name;
currentNode.attributes['onclick'].value = currentNode.attributes['onclick'].value.replace(re, this.field + "_collection_" + this.fields_count);
currentNode.attributes['onclick'].value = currentNode.attributes['onclick'].value.replace(RegExp(this.field + "_collection_extra_0", 'g'), this.field + "_collection_extra_" + this.fields_count);
break;
case "allow_new_value_" + toreplace:
currentNode.name = new_name;
currentNode.id = new_name;
break;
case "remove_" + toreplace:
currentNode.name = new_name;
currentNode.id = new_name;
currentNode.setAttribute('collection_id', this.field_element_name);
currentNode.setAttribute('remove_id', this.fields_count);
currentNode.onclick = function() {
collection[this.getAttribute('collection_id')].remove(this.getAttribute('remove_id'));
};
break;
case "primary_" + this.field + "_collection":
currentNode.id = new_name;
currentNode.value = this.fields_count;
currentNode.checked = false; //Firefox
currentNode.setAttribute('defaultChecked', '');
break;
default:
//alert(name);
break;
} //switch
} //if-else
},
/*
* Collapse or expand the rows to show for the editview(depending of the this.more_status attribute).
*/
js_more: function(val){
if(this.show_more_image){
var more_ = document.getElementById('more_img_'+this.field_element_name);
var arrow = document.getElementById('arrow_'+this.field);
var radios = this.get_radios();
// if we want to collapse
if(this.more_status == false){
more_.src = "index.php?entryPoint=getImage&themeName="+SUGAR.themes.theme_name+"&imageName=advanced_search.gif";
this.more_status = true;
// show the primary only and hidde the other one.
var hidden_count = 0;
for(var k=0; k< radios.length; k++){
if (radios[k].type && radios[k].type == 'radio') {
if (radios[k].checked) {
radios[k].parentNode.parentNode.parentNode.style.display = '';
} else {
radios[k].parentNode.parentNode.parentNode.style.display = 'none';
hidden_count++;
}
}
}
//rrs - add code to not remove the first field if non if the fields are selected as primary
if(hidden_count == radios.length){
radios[0].parentNode.parentNode.parentNode.style.display = '';
}
arrow.value = 'hide';
}else{
more_.src = "index.php?entryPoint=getImage&themeName="+SUGAR.themes.theme_name+"&imageName=basic_search.gif";
this.more_status=false;
// display all the records
for(var k=0; k< radios.length; k++){
if(isInteger(k)){
radios[k].parentNode.parentNode.parentNode.style.display='';
}
}
arrow.value = 'show';
}
var more_div = document.getElementById('more_div_'+this.field_element_name);
if(more_div) {
more_div.innerHTML = arrow.value == 'show' ? SUGAR.language.get('app_strings','LBL_HIDE') : SUGAR.language.get('app_strings','LBL_SHOW');
}
}
},
/*
* Create the clone on load of the page and store it in this.cloneField
*/
create_clone: function() {
var oneField = document.getElementById('lineFields_'+this.field_element_name+'_0');
if(oneField == null || typeof(oneField) == 'undefined')return false;
this.cloneField[0] = oneField.cloneNode(true);
this.cloneField[1] = oneField.parentNode;
this.more_status = true;
clone_id = this.form + '_' + this.field + '_collection_0';
if (typeof sqs_objects[clone_id] != 'undefined') {
var clone = YAHOO.lang.JSON.stringify(sqs_objects[clone_id]);
eval('this.sqs_clone=' + clone);
return true;
}
return false;
},
/**
* Validates team set to check if the primary team id has been set or not
*/
validateTemSet : function(formname, fieldname) {
table_element_id = formname + '_' + fieldname + '_table';
if(document.getElementById(table_element_id)) {
input_elements = YAHOO.util.Selector.query('input[type=radio]', document.getElementById(table_element_id));
has_primary = false;
primary_field_id = fieldname + '_collection_0';
for(t in input_elements) {
primary_field_id = fieldname + '_collection_' + input_elements[t].value;
if(input_elements[t].type && input_elements[t].type == 'radio' && input_elements[t].checked == true) {
if(document.forms[formname].elements[primary_field_id].value != '') {
has_primary = true;
}
break;
}
}
if(!has_primary) {
return false;
}
return true;
}
return true;
},
/**
* return an array of teamids for a team field
*/
getTeamIdsfromUI: function(formname, fieldname) {
$team_ids = new Array();
table_element_id = formname + '_' + fieldname + '_table';
if(document.getElementById(table_element_id)) {
input_elements = YAHOO.util.Selector.query('input[type=hidden]', document.getElementById(table_element_id));
for(t in input_elements) {
if (input_elements[t].id.match("id_" + fieldname + "_collection_") != null) {
$team_ids.push(input_elements[t].value);
} // if
} // for
} // if
return $team_ids;
},
/**
* return a primary team id
*/
getPrimaryTeamidsFromUI: function(formname, fieldname) {
table_element_id = formname + '_' + fieldname + '_table';
if(document.getElementById(table_element_id)) {
input_elements = YAHOO.util.Selector.query('input[type=radio]', document.getElementById(table_element_id));
for(t in input_elements) {
primary_field_id = 'id_' + document.forms[formname][fieldname].name + '_collection_' + input_elements[t].value;
if(input_elements[t].type && input_elements[t].type == 'radio' && input_elements[t].checked == true) {
if(document.forms[formname].elements[primary_field_id].value != '') {
return document.forms[formname].elements[primary_field_id].value;
} // if
} // if
} // for
} // if
return '';
},
/*
* Change the primary row onchange of the radio button.
*/
changePrimary: function(noAdd){
var old_primary = this.primary_field;
var radios=this.get_radios();
for (var k = 0; k < radios.length; k++) {
var qs_id = radios[k].id.replace('primary_','');
if (radios[k].checked) {
this.primary_field = qs_id;
} else {
qs_id = qs_id + '_' + k;
}
qs_id = this.form + '_' + qs_id;
if(typeof sqs_objects[qs_id] != 'undefined' && sqs_objects[qs_id]['primary_field_list']){
for (var ii = 0; ii < sqs_objects[qs_id]['primary_field_list'].length; ii++) {
if (radios[k].checked && qs_id != old_primary) {
sqs_objects[qs_id]['field_list'].push(sqs_objects[qs_id]['primary_field_list'][ii]);
sqs_objects[qs_id]['populate_list'].push(sqs_objects[qs_id]['primary_populate_list'][ii]);
}else if(old_primary == qs_id && !radios[k].checked){
sqs_objects[qs_id]['field_list'].pop();
sqs_objects[qs_id]['populate_list'].pop();
}
}
}
}
if (noAdd) {
enableQS(false);
}
this.first = false;
},
/*
* Collapse or expand the rows to show for the detailview.
*/
js_more_detail: function(id){
var more_img = document.getElementById('more_img_'+id);
if(more_img.style.display == 'inline'){
more_img.src = "index.php?entryPoint=getImage&themeName="+SUGAR.themes.theme_name+"&imageName=advanced_search.gif";
}else{
more_img.src = "index.php?entryPoint=getImage&themeName="+SUGAR.themes.theme_name+"&imageName=basic_search.gif";
}
},
/*
* Replace the first field with the specified values
*/
replace_first: function(values){
for (var i = 0; i <= this.fields_count; i++) {
div_el = document.getElementById(this.field_element_name + '_input_div_' + i);
if(div_el) {
var name_field = document.forms[this.form].elements[this.field+"_collection_" + i];
var id_field = document.forms[this.form].elements["id_"+this.field+"_collection_" + i];
name_field.value = values['name'];
id_field.value = values['id'];
break;
}
}
},
/*
* Remove all empty fields from the widget.
*/
clean_up: function(){
//clean up any rows that have been added but do not contain any data
var divsToClean = new Array();
var isFirstFieldEmpty = false;
var divCount = 0;
for (var i = 0; i <= this.fields_count; i++) {
div_el = document.getElementById(this.field_element_name + '_input_div_' + i);
if(div_el) {
input_els = div_el.getElementsByTagName('input');
for(x in input_els) {
if(input_els[x].id && input_els[x].id == (this.field + '_collection_' + i) && trim(input_els[x].value) == '') {
if(divCount == 0){
isFirstFieldEmpty = true;
} else {
divsToClean.push(i);
}
}
}
divCount++;
}
}
for(var j = 0; j < divsToClean.length; j++){
this.remove(divsToClean[j]);
}
return isFirstFieldEmpty;
},
show_arrow_label: function(show) {
var more_div = document.getElementById('more_div_'+this.field_element_name);
if(more_div) {
more_div.style.display = show ? '' : 'none';
}
},
/**
* is_expanded
* helper function to determine whether or not the widget is expanded (all teams are shown)
*/
is_expanded: function() {
var more_div = document.getElementById('more_div_'+this.field_element_name);
if(more_div) {
return more_div.style.display == '';
}
return false;
}
}
}

View File

@@ -0,0 +1,229 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
/**
* Datetimecombo.js
* This is a javascript object that handles rendering the non-date portions
* of a datetime field. There are some assumptions that are made so this
* class serves more as a utility rather than a building block. It is used
* primarily to handle the datetime field shown for Call, Meetings and Tasks
* edit views.
*/
/*
* Datetimecombo constructor
* @param datetime
* @param fieldname
* @param timeformat
* @param tabindex
* @allowEmptyHM - if this param was set true , the hour and minute select field will has an empty option.
*/
function Datetimecombo (datetime, field, timeformat, tabindex, showCheckbox, checked, allowEmptyHM) {
this.datetime = datetime;
this.allowEmptyHM = allowEmptyHM;
if(typeof this.datetime == "undefined" || datetime == '' || trim(datetime).length < 10) {
this.datetime = "";
var d = new Date();
var month = d.getMonth();
var date = d.getDate();
var year = d.getYear();
var hours = d.getHours();
var minutes = d.getMinutes();
}
this.fieldname = field;
//Get hours and minutes and adjust as necessary
this.hrs = parseInt(datetime.substring(11,13), 10);
this.mins = parseInt(datetime.substring(14,16), 10);
//A safety scan to make sure hrs and minutes are formatted correctly
if (this.mins > 0 && this.mins < 15) {
this.mins = 15;
} else if (this.mins > 15 && this.mins < 30) {
this.mins = 30;
} else if (this.mins > 30 && this.mins < 45) {
this.mins = 45;
} else if (this.mins > 45) {
this.hrs += 1;
this.mins = 0;
} //if-else
this.timeformat = timeformat; //23:00 || 11:00
this.tabindex = tabindex == null || isNaN(tabindex) ? 1 : tabindex;
// Calculate other derived values
this.timeseparator = this.timeformat.substring(2,3);
this.has12Hours = /^11/.test(this.timeformat);
this.hasMeridiem = /am|pm/i.test(this.timeformat);
if(this.hasMeridiem) {
this.pm = /pm/.test(this.timeformat);
}
this.meridiem = this.hasMeridiem ? trim(this.datetime.substring(16)) : '';
this.datetime = this.datetime.substr(0,10);
this.showCheckbox = showCheckbox;
this.checked = checked;
document.getElementById(this.fieldname + '_date').value = this.datetime;
}
/**
* jsscript
* This function renders the javascript portion to handle updates
* on the calendar widget. We have to do this because browsers like Mozilla
* have errors when attempting to handle events inside a class function.
* This is the reason why this code that is generated is not placed within
* the update function of the Datetimecombo class. Instead, it is run
* using the eval() method when the widget is loaded.
*/
Datetimecombo.prototype.jsscript = function(callback) {
//text = '\n<script language="javascript" type="text/html">';
text = '\nfunction update_' + this.fieldname + '(calendar) {';
text += '\nif(calendar != null) {';
text += '\ncalendar.onUpdateTime();';
text += '\ncalendar.onSetTime();';
text += '\ncalendar.hide();';
text += '\n}'
text += '\nd = document.getElementById("' + this.fieldname + '_date").value;';
text += '\nh = document.getElementById("' + this.fieldname + '_hours").value;';
text += '\nm = document.getElementById("' + this.fieldname + '_minutes").value;';
text += '\nnewdate = d + " " + h + "' + this.timeseparator + '" + m;';
if(this.hasMeridiem) {
text += '\nif(typeof document.getElementById("' + this.fieldname + '_meridiem") != "undefined") {';
text += '\n newdate += document.getElementById("' + this.fieldname + '_meridiem").value;';
text += '\n}';
}
text += '\nif(trim(newdate) =="'+ this.timeseparator +'") newdate="";';
text += '\ndocument.getElementById("' + this.fieldname + '").value = newdate;';
text += '\n' + callback;
text += '\n}';
//text += '\n</script>';
return text;
}
/**
* html
* This function renders the HTML form elements for this widget
*/
Datetimecombo.prototype.html = function(callback) {
//Now render the items
var text = '<select class="datetimecombo_time" size="1" id="' + this.fieldname + '_hours" tabindex="' + this.tabindex + '" onchange="combo_' + this.fieldname + '.update(); ' + callback + '">';
var h1 = this.has12Hours ? 1 : 0;
var h2 = this.has12Hours ? 12 : 23;
if(this.allowEmptyHM){
text += '<option></option>';
}
for(i=h1; i <= h2; i++) {
val = i < 10 ? "0" + i : i;
text += '<option value="' + val + '" ' + (i == this.hrs ? "SELECTED" : "") + '>' + val + '</option>';
}
text += '\n</select>&nbsp;';
text += this.timeseparator;
text += '\n&nbsp;<select class="datetimecombo_time" size="1" id="' + this.fieldname + '_minutes" tabindex="' + this.tabindex + '" onchange="combo_' + this.fieldname + '.update(); ' + callback + '">';
if(this.allowEmptyHM){
text += '\n<option></option>';
}
text += '\n<option value="00" ' + (this.mins == 0 ? "SELECTED" : "") + '>00</option>';
text += '\n<option value="15" ' + (this.mins == 15 ? "SELECTED" : "") + '>15</option>';
text += '\n<option value="30" ' + (this.mins == 30 ? "SELECTED" : "") + '>30</option>';
text += '\n<option value="45" ' + (this.mins == 45 ? "SELECTED" : "") + '>45</option>';
text += '\n</select>';
if(this.hasMeridiem) {
text += '\n&nbsp;';
text += '\n<select class="datetimecombo_time" size="1" id="' + this.fieldname + '_meridiem" tabindex="' + this.tabindex + '" onchange="combo_' + this.fieldname + '.update(); ' + callback + '">';
if(this.allowEmptyHM){
text += '\n<option></option>';
}
text += '\n<option value="' + (this.pm ? "am" : "AM") + '" ' + (/am/i.test(this.meridiem) ? "SELECTED" : "") + '>' + (this.pm ? "am" : "AM") + '</option>';
text += '\n<option value="' + (this.pm ? "pm" : "PM") + '" ' + (/pm/i.test(this.meridiem) ? "SELECTED" : "") + '>' + (this.pm ? "pm" : "PM") + '</option>';
text += '\n</select>';
}
if(this.showCheckbox) {
text += '\n<input style="visibility:hidden;" type="checkbox" name="' + this.fieldname + '_flag" id="' + this.fieldname + '_flag" tabindex="' + this.tabindex + '" onchange="combo_' + this.fieldname + '.update(); ' + callback + '" ' + (this.checked ? 'CHECKED' : '') + '>';
//text += '&nbsp;' + SUGAR.language.get("app_strings", "LBL_LINK_NONE");
}
return text;
};
/**
* update
* This method handles events on the hour, minute and meridiem elements for the widget
*
*/
Datetimecombo.prototype.update = function() {
id = this.fieldname + '_date';
d = window.document.getElementById(id).value;
id = this.fieldname + '_hours';
h = window.document.getElementById(id).value;
id = this.fieldname + '_minutes';
m = window.document.getElementById(id).value;
newdate = d + ' ' + h + this.timeseparator + m;
if(this.hasMeridiem) {
ampm = document.getElementById(this.fieldname + "_meridiem").value;
newdate += ampm;
}
if(trim(newdate) == ""+this.timeseparator+""){
newdate = '';
}
document.getElementById(this.fieldname).value = newdate;
if(this.showCheckbox) {
flag = this.fieldname + '_flag';
date = this.fieldname + '_date';
hours = this.fieldname + '_hours';
mins = this.fieldname + '_minutes';
if(document.getElementById(flag).checked) {
document.getElementById(flag).value=1;
document.getElementById(this.fieldname).value = '';
document.getElementById(date).disabled=true;
document.getElementById(hours).disabled=true;
document.getElementById(mins).disabled=true;
} else {
document.getElementById(flag).value=0;
document.getElementById(date).disabled=false;
document.getElementById(hours).disabled=false;
document.getElementById(mins).disabled=false;
}
}
};

View File

@@ -0,0 +1,79 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
function CompanyDetailsDialog(div_id, text, x, y)
{
this.div_id = div_id;
this.text = text;
this.width = 300;
this.header = '';
this.footer = '';
this.x = x;
this.y = y;
}
function header(header)
{
this.header = header;
}
function footer(footer)
{
this.footer = footer;
}
function display() {
dialog = new YAHOO.widget.SimpleDialog(this.div_id,
{ width: this.width,
//fixedcenter: true,
visible: true,
draggable: true,
close: true,
text: this.text,
constraintoviewport: true,
x: this.x,
y: this.y
} );
dialog.setHeader(this.header);
dialog.setBody(this.text);
dialog.setFooter(this.footer);
dialog.render(document.body);
dialog.show();
}
CompanyDetailsDialog.prototype.setHeader = header;
CompanyDetailsDialog.prototype.setFooter = footer;
CompanyDetailsDialog.prototype.display = display;

View File

@@ -0,0 +1,120 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
function Get_Cookie(name) {
var start = document.cookie.indexOf(name + '=');
var len = start + name.length + 1;
if ((!start) && (name != document.cookie.substring(0,name.length)))
return null;
if (start == -1)
return null;
var end = document.cookie.indexOf(';',len);
if (end == -1) end = document.cookie.length;
if(end == start){
return '';
}
return unescape(document.cookie.substring(len,end));
}
function Set_Cookie( name, value, expires, path, domain, secure )
{
// set time, it's in milliseconds
var today = new Date();
today.setTime( today.getTime() );
/*
if the expires variable is set, make the correct
expires time, the current script below will set
it for x number of days, to make it for hours,
delete * 24, for minutes, delete * 60 * 24
*/
if ( expires )
{
expires = expires * 1000 * 60 * 60 * 24;
}
var expires_date = new Date( today.getTime() + (expires) );
document.cookie = name + "=" +escape( value ) +
( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
( ( path ) ? ";path=" + path : "" ) +
( ( domain ) ? ";domain=" + domain : "" ) +
( ( secure ) ? ";secure" : "" );
}
function Delete_Cookie(name,path,domain) {
if (Get_Cookie(name))
document.cookie =
name + '=' +
( (path) ? ';path=' + path : '') +
( (domain) ? ';domain=' + domain : '') +
';expires=Thu, 01-Jan-1970 00:00:01 GMT';
}
/*
returns an array of cookie values from a single cookie
*/
function get_sub_cookies(cookie){
var cookies = new Array();
var end ='';
if(cookie && cookie != ''){
end = cookie.indexOf('#')
while(end > -1){
var cur = cookie.substring(0, end);
cookie = cookie.substring(end + 1, cookie.length);
var name = cur.substring(0, cur.indexOf('='));
var value = cur.substring(cur.indexOf('=') + 1, cur.length);
cookies[name] = value;
end = cookie.indexOf('#')
}
}
return cookies;
}
function subs_to_cookie(cookies){
var cookie = '';
for (var i in cookies)
{
if (typeof(cookies[i]) != "function") {
cookie += i + '=' + cookies[i] + '#';
}
}
return cookie;
}

View File

@@ -0,0 +1,81 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
SUGAR.dashlets = function() {
return {
/**
* Generic javascript method to use post a form
*
* @param object theForm pointer to the form object
* @param function callback function to call after for form is sent
*
* @return bool false
*/
postForm: function(theForm, callback) {
var success = function(data) {
if(data) {
callback(data.responseText);
}
}
YAHOO.util.Connect.setForm(theForm);
var cObj = YAHOO.util.Connect.asyncRequest('POST', 'index.php', {success: success, failure: success});
return false;
},
/**
* Generic javascript method to use Dashlet methods
*
* @param string dashletId Id of the dashlet being call
* @param string methodName method to be called (function in the dashlet class)
* @param string postData data to send (eg foo=bar&foo2=bar2...)
* @param bool refreshAfter refreash the dashlet after sending data
* @param function callback function to be called after dashlet is refreshed (or not refresed)
*/
callMethod: function(dashletId, methodName, postData, refreshAfter, callback) {
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING'));
response = function(data) {
ajaxStatus.hideStatus();
if(refreshAfter) SUGAR.mySugar.retrieveDashlet(dashletId);
if(callback) {
callback(data.responseText);
}
}
post = 'to_pdf=1&module=Home&action=CallMethodDashlet&method=' + methodName + '&id=' + dashletId + '&' + postData;
var cObj = YAHOO.util.Connect.asyncRequest('POST','index.php',
{success: response, failure: response}, post);
}
};
}();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,223 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
//////////////////////////////////////////////////////////////////
// called on the return of a JSON-RPC async request,
// and calls the display() method on the widget registered
// in the registry at the request_id key returned by the server
//////////////////////////////////////////////////////////////////
function method_callback (request_id,rslt,e) {
if(rslt == null) {
return;
}
if(typeof (global_request_registry[request_id]) != 'undefined') {
widget = global_request_registry[request_id][0];
method_name = global_request_registry[request_id][1];
widget[method_name](rslt);
}
}
//////////////////////////////////////////////////
// class: SugarVCalClient
// async retrieval/parsing of vCal freebusy info
//
//////////////////////////////////////////////////
SugarClass.inherit("SugarVCalClient","SugarClass");
function SugarVCalClient() {
this.init();
}
SugarVCalClient.prototype.init = function(){
//this.urllib = importModule("urllib");
}
SugarVCalClient.prototype.load = function(user_id,request_id){
this.user_id = user_id;
// get content at url and declare the callback using anon function:
urllib.getURL('./vcal_server.php?type=vfb&source=outlook&user_id='+user_id,[["Content-Type", "text/plain"]], function (result) {
if (typeof GLOBAL_REGISTRY.freebusy == 'undefined')
{
GLOBAL_REGISTRY.freebusy = new Object();
}
if (typeof GLOBAL_REGISTRY.freebusy_adjusted == 'undefined')
{
GLOBAL_REGISTRY.freebusy_adjusted = new Object();
}
// parse vCal and put it in the registry using the user_id as a key:
GLOBAL_REGISTRY.freebusy[user_id] = SugarVCalClient.parseResults(result.responseText, false);
// parse for current user adjusted vCal
GLOBAL_REGISTRY.freebusy_adjusted[user_id] = SugarVCalClient.parseResults(result.responseText, true);
// now call the display() on the widget registered at request_id:
global_request_registry[request_id][0].display();
})
}
// parse vCal freebusy info and return object
SugarVCalClient.prototype.parseResults = function(textResult, adjusted){
var match = /FREEBUSY.*?\:([\w]+)\/([\w]+)/g;
// datetime = new SugarDateTime();
var result;
var timehash = new Object();
var dst_start;
var dst_end;
if(GLOBAL_REGISTRY.current_user.fields.dst_start == null)
dst_start = '19700101T000000Z';
else
dst_start = GLOBAL_REGISTRY.current_user.fields.dst_start.replace(/ /gi, 'T').replace(/:/gi,'').replace(/-/gi,'') + 'Z';
if(GLOBAL_REGISTRY.current_user.fields.dst_end == null)
dst_end = '19700101T000000Z';
else
dst_end = GLOBAL_REGISTRY.current_user.fields.dst_end.replace(/ /gi, 'T').replace(/:/gi,'').replace(/-/gi,'') + 'Z';
gmt_offset_secs = GLOBAL_REGISTRY.current_user.fields.gmt_offset * 60;
// loop thru all FREEBUSY matches
while(((result= match.exec(textResult))) != null)
{
var startdate;
var enddate;
if(adjusted) {// send back adjusted for current_user
startdate = SugarDateTime.parseAdjustedDate(result[1], dst_start, dst_end, gmt_offset_secs);
enddate = SugarDateTime.parseAdjustedDate(result[2], dst_start, dst_end, gmt_offset_secs);
}
else { // GMT
startdate = SugarDateTime.parseUTCDate(result[1]);
enddate = SugarDateTime.parseUTCDate(result[2]);
}
var startmins = startdate.getUTCMinutes();
// pick the start slot based on the minutes
if ( startmins >= 0 && startmins < 15) {
startdate.setUTCMinutes(0);
}
else if ( startmins >= 15 && startmins < 30) {
startdate.setUTCMinutes(15);
}
else if ( startmins >= 30 && startmins < 45) {
startdate.setUTCMinutes(30);
}
else {
startdate.setUTCMinutes(45);
}
// starting at startdate, create hash of each busy 15 min
// timeslot and store as a key
for(var i=0;i<100;i++)
{
if (startdate.valueOf() < enddate.valueOf())
{
var hash = SugarDateTime.getUTCHash(startdate);
if (typeof (timehash[hash]) == 'undefined')
{
timehash[hash] = 0;
}
timehash[hash] += 1;
startdate = new Date(startdate.valueOf()+(15*60*1000));
}
else
{
break;
}
}
}
return timehash;
}
SugarVCalClient.parseResults = SugarVCalClient.prototype.parseResults;
//////////////////////////////////////////////////
// class: SugarRPCClient
// wrapper around async JSON-RPC client class
//
//////////////////////////////////////////////////
SugarRPCClient.allowed_methods = ['retrieve','query','save','set_accept_status','get_objects_from_module', 'email', 'get_user_array', 'get_full_list'];
SugarClass.inherit("SugarRPCClient","SugarClass");
function SugarRPCClient() {
this.init();
}
/*
* PUT NEW METHODS IN THIS ARRAY:
*/
SugarRPCClient.prototype.allowed_methods = ['retrieve','query','save','set_accept_status', 'get_objects_from_module', 'email', 'get_user_array', 'get_full_list'];
SugarRPCClient.prototype.init = function() {
this._serviceProxy;
this._showError= function (e){
alert("ERROR CONNECTING to: ./index.php?entryPoint=json_server, ERROR:"+e);
}
this.serviceURL = './index.php?entryPoint=json_server';
this._serviceProxy = new jsonrpc.ServiceProxy(this.serviceURL,this.allowed_methods);
}
// send a 3rd argument of value 'true' to make the call synchronous.
// in synchronous mode, the return will be the result.
// in asynchronous mode, the return will be the request_id to map the call-back function to.
SugarRPCClient.prototype.call_method = function(method,args) {
var self=this;
try {
var the_result;
if(arguments.length == 3 && arguments[2] == true) {
// aha! fooled you! this function can be called synchronous!
the_result = this._serviceProxy[method](args);
} else {
// make the call asynchronous
this._serviceProxy[method](args, method_callback);
the_result = this._serviceProxy.httpConn.request_id;
}
return the_result;
} catch(e) {//error before calling server
this._showError(e);
}
}
var global_rpcClient = new SugarRPCClient();

View File

@@ -0,0 +1,774 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
// inline modules, don't do importmodule!
// from file langlite.js
langlite = Module("langlite", "0.3.7", function(mod){
mod.JSONParser=Class("JSONParser", function(publ, supr){
publ.init=function(){
this.libs = {};
}
publ.addLib = function(obj, name, exports){
if(exports == null){
this.libs[name] = obj;
}else{
for(var i=0;i<exports.length;i++){
this.libs[name + "." + exports[i]] = obj[exports[i]];
}
}
}
publ.objToJson=function(obj){
if(obj == null){
return "null";
}else{
return mod.objToJson(obj);
}
}
})
mod.parser = new mod.JSONParser();
/**
Turns JSON code into JavaScript objects.
@param src The source as a String.
*/
mod.jsonToObj=function(src){
return mod.parser.jsonToObj(src);
}
var json_types = new Object();
json_types['object'] = function(obj){
var v=[];
for(attr in obj){
if(typeof obj[attr] != "function"){
v.push('"' + attr + '": ' + mod.objToJson(obj[attr]));
}
}
return "{" + v.join(", ") + "}";
}
json_types['string'] = function(obj){
var s = '"' + obj.replace(/(["\\])/g, '\\$1') + '"';
s = s.replace(/(\n)/g,"\\n");
return s;
}
json_types['number'] = function(obj){
return obj.toString();
}
json_types['boolean'] = function(obj){
return obj.toString();
}
json_types['date'] = function(obj){
var padd=function(s, p){
s=p+s
return s.substring(s.length - p.length)
}
var y = padd(obj.getUTCFullYear(), "0000");
var m = padd(obj.getUTCMonth() + 1, "00");
var d = padd(obj.getUTCDate(), "00");
var h = padd(obj.getUTCHours(), "00");
var min = padd(obj.getUTCMinutes(), "00");
var s = padd(obj.getUTCSeconds(), "00");
var isodate = y + m + d + "T" + h + ":" + min + ":" + s
return '{"jsonclass":["sys.ISODate", ["' + isodate + '"]]}';
}
json_types['array'] = function(obj){
var v = [];
for(var i=0;i<obj.length;i++){
v.push(mod.objToJson(obj[i])) ;
}
return "[" + v.join(", ") + "]";
}
mod.objToJson=function(obj){
if ( typeof(obj) == 'undefined')
{
return '';
}
if ( typeof(json_types[typeof(obj)]) == 'undefined')
{
alert('class not defined for toJSON():'+typeof(obj));
}
return json_types[typeof(obj)](obj);
}
mod.test=function(){
try{
print(mod.objToJson(['sds', -12377,-1212.1212, 12, '-2312']));
}catch(e){
print(e.toTraceString());
}
}
})
// from file jsonrpclite.js
jsonrpclite = Module("jsonrpclite", "0.3.2", function(mod){
// SUGARCRM:
var lang = langlite // inline module
// var lang = importModule("langlite");
// END SUGARCRM
var tokens = lang.tokens;
var ObjectBuffer=Class("ObjectBuffer", function(publ, supr){
publ.init=function(){
this.data="";
}
publ.getObjects=function(data){
this.data += data;
var t = new lang.Tokenizer(this.data);
var brCnt= 0;
var objects = [];
var readCnt = 0
while(! t.finished()){
var n = t.next();
if(n.type != tokens.ERR){
if(n.value == "{"){
brCnt+=1;
}else if(n.value == "}"){
brCnt-=1;
if(brCnt==0){
var s = this.data.slice(readCnt, n.pos+1);
readCnt += s.length;
objects.push(s);
}
}
}else{
break;
}
}
this.data = this.data.slice(readCnt);
return objects;
}
})
var nameAllowed=function(name){
return name.match(/^[a-zA-Z]\w*$/) != null;
}
var getMethodByName=function(obj, name){
try{//to get a method by asking the service
obj = obj._getMethodByName(name)
}catch(e){
var names = name.split(".");
for(var i=0;i<names.length;i++){
name = names[i];
if(nameAllowed(name)){
obj = obj[name];
}
}
}
return obj;
}
var Response=Class("Response", function(publ, supr){
publ.init=function(id, result, error){
this.id=id;
this.result = result;
this.error = error;
}
publ._toJSON=function(){
var p = [lang.objToJson(this.id), lang.objToJson(this.result),lang.objToJson(this.error)];
return '{"id":' + p[0] + ', "result":' + p[1] + ', "error":' + p[2] + "}";
}
})
var Request=Class("Request", function(publ, supr){
publ.init=function(id, method, params){
this.id=id;
this.method = method;
this.params = params;
/*
var str = '';
for(hello in this.params)
{
str += "var:"+hello+":"+this.params[hello]+":\n";
}
alert(str);
*/
}
publ._toJSON=function(){
var p = [lang.objToJson(this.id), lang.objToJson(this.method),lang.objToJson(this.params)];
return '{"id":' + p[0] + ', "method":' + p[1] + ', "params":' + p[2] + "}";
}
})
var Notification=Class("Notification", function(publ, supr){
publ.init=function(method, params){
this.method = method;
this.params = params;
}
publ._toJSON=function(){
var p = [lang.objToJson(this.method),lang.objToJson(this.params)];
return '{"method":' + p[0] + ', "params":' + p[1] + "}";
}
})
var ResponseHandler=Class("ResponseHandler", function(publ, supr){
publ.init=function(callback){
this.callback=callback;
}
publ.handleResponse=function(resp){
this.callback(resp.result, resp.error);
}
})
var RPCLib = Class("RPCLib", function(publ, supr){
})
var BaseConnectionHandler = Class("BaseConnectionHandler", function(publ, supr){
publ.init=function(service){
this.service = service;
this.jsonParser = new lang.JSONParser();
this.jsonParser.addLib(new RPCLib(), "rpc", []);
this.respHandlers = [];
this.objBuffer = new ObjectBuffer();
}
publ.addResponseHandler=function(cb){
var id=1;
while(this.respHandlers[""+id] ){
id+=1;
}
id="" + id;
this.respHandlers[id] = new ResponseHandler(cb);
return id;
}
publ.send = function(data){
}
publ.sendNotify = function(name, args){
var n = new Notification(name, args);
n = this.jsonParser.objToJson(n);
this.send(n)
}
publ.sendRequest = function(name, args, callback){
var id = this.addResponseHandler(callback);
var r = new Request(id, name, args);
r = this.jsonParser.objToJson(r);
this.send(r);
}
publ.sendResponse = function(id, result, error){
var r = new Response(id, result, error);
r = this.jsonParser.objToJson(r);
this.send(r);
}
publ.handleRequest = function(req){
var name = req.method;
var params = req.params;
var id=req.id;
if(this.service[name]){
try{
var rslt = this.service[name].apply(this.service,params);
this.sendResponse(id, rslt, null)
}catch(e){
this.sendResponse(id, null, new ApplicationError("" + e))
}
}else{
this.sendResponse(id, null, new MethodNotFound());
}
}
publ.handleNotification = function(notif){
if(this.service[notif.method]){
try{
this.service[notif.method].apply(this.service, notif.params);
}catch(e){
}
}
}
publ.handleResponse = function(resp){
var id=resp.id;
var h = this.respHandlers[id];
h.handleResponse(resp)
delete this.respHandlers[id]
}
publ.handleData = function(data){
var objs = this.objBuffer.getObjects(data);
for(var i=0;i<objs.length;i++){
try{
var obj = this.jsonParser.jsonToObj(objs[i]);
}catch(e){
throw "Not well formed";
}
if(obj.method != null){
if(obj.id != null){
this.handleRequest(new Request(obj.id, obj.method, obj.params));
}else{
this.handleNotification(new Notification(obj.method, obj.params));
}
}else if(obj.id != null){
this.handleResponse(new Response(obj.id, obj.result, obj.error));
}else{
throw "Unknown Data";
}
}
}
})
var SocketConnectionHandler = Class("SocketConnectionHandler", BaseConnectionHandler, function(publ, supr){
publ.init=function(socket, localService){
this.socket = socket;
socket.addEventListener("connectionData", this, false);
supr(this).init( localService);
}
publ.handleEvent=function(evt){
this.handleData(evt.data);
}
publ.send=function(data){
this.socket.send(data);
}
publ.close=function(data){
this.socket.close();
}
})
var HTTPConnectionHandler = Class("HTTPConnectionHandler", BaseConnectionHandler, function(publ, supr){
var urllib;
publ.request_id = 1;
publ.init=function(url, localService){
urllib=importModule("urllib");
this.url = url;
supr(this).init( localService);
}
publ.handleData = function(data){
try{
var obj = JSON.parse(data);
}catch(e){;
throw " Not well formed\n\n" + e + "\n\nResponse from server:\n\n " + data;
}
if(obj.id != null){
return obj;
}else{
throw "Unknown Data (No id property found)";
}
}
publ.sendRequest = function(name, args, callback){
var sync = false;
if(typeof callback != "function"){//see if it is sync
args.push(callback);
sync=true;
}
var data = new Request(this.request_id++, name, args);
// cn: bug 12274 - defend against CSRF
data = JSON.stringify(data); // creates security envelope wrapped JSON object
if(sync){
var rsp = urllib.postURL(this.url, data, [["Content-Type", "text/plain"]]);
rsp = this.handleData(rsp.responseText);
if(rsp.error){
throw rsp.error;
}else{
return rsp.result;
}
}else{//async connection uses the respHandler to handle the repsonse
var self = this;
var request_id = this.request_id;
urllib.postURL(this.url, data, [["Content-Type", "text/plain"]], function(rsp){
try{
rsp = self.handleData(rsp.responseText);
}catch(e){
//callback(null,e);
callback(request_id,null,e);
return;
}
callback(request_id,rsp.result, rsp.error);
//callback(this.request_id,rsp.result, rsp.error);
//callback(rsp.result, rsp.error);
});
}
}
publ.sendNotify = function(name, args){
var data = new Notification(name, args);
data = this.jsonParser.objToJson(data);
urllib.postURL(this.url, data, [["Content-Type", "text/plain"]], function(rsp){});
}
})
var PeerObject=Class("PeerObject", function(publ, supr){
publ.init=function(name, conn){
var fn=function(){
var args=[];
for(var i=0;i<arguments.length;i++){
args[i] = arguments[i];
}
var cb=args.pop();
return conn.sendRequest(name, args, cb);
}
return fn;
}
})
var PeerNotifyObject=Class("PeerNotifyObject", function(publ, supr){
publ.init=function(name, conn){
var fn=function(){
var args=[];
for(var i=0;i<arguments.length;i++){
args[i] = arguments[i];
}
conn.sendNotify(name, args);
}
return fn;
}
})
var BasePeer = Class("BasePeer", function(publ, supr){
publ.init=function(conn, methodNames){
this._conn = conn;
this.notify = new PeerObject("notify", conn);
this._add(methodNames);
}
var setupPeerMethod=function(root, methodName, conn, MethClass){
var names = methodName.split(".");
var obj = root;
for(var n=0;n<names.length-1;n++){
var name = names[n];
if(obj[name]){
obj = obj[name];
}else{
obj[name] = new Object();
obj = obj[name];
}
}
var name = names[names.length-1];
if(obj[name]){
}else{
var mth = new MethClass(methodName, conn);
obj[name] = mth;
}
}
publ._add = function(methodNames){
for(var i=0;i<methodNames.length;i++){
setupPeerMethod(this, methodNames[i], this._conn, PeerObject);
setupPeerMethod(this.notify, methodNames[i], this._conn, PeerNotifyObject);
}
}
})
mod.ServiceProxy = Class("ServiceProxy", BasePeer, function(publ, supr){
publ.init = function(url, methodNames, localService){
var n = url.match(/^jsonrpc:\/\/(.*:\d*)$/);
if(n!=null){//is it json-rpc over TCP protocoll
var hostaddr = n[1];
try{
var socket = createConnection();
}catch(e){
throw "Can't create a socket connection."
}
socket.connect(hostaddr);
supr(this).init( new SocketConnectionHandler(socket, localService), methodNames);
}else{//or is it json-rpc over http
this.httpConn = new HTTPConnectionHandler(url, localService);
supr(this).init( this.httpConn, methodNames);
}
}
})
})
jsolait.baseURL = 'include/jsolait/lib';
urllib = importModule('urllib');
var global_request_registry = new Object();
///////////////////////////////////////////////
// Class SugarClass
// superclass for all Sugar* sub-classes
//
///////////////////////////////////////////////
function SugarClass()
{
// if ( arguments.length > 0 )
this.init();
}
SugarClass.prototype.init = function() {
}
// create inheritance for a class
SugarClass.inherit = function(className,parentClassName) {
var str = className+".prototype = new "+parentClassName+"();";
str += className+".prototype.constructor = "+className+";";
str += className+".superclass = "+parentClassName+".prototype;";
try {
eval(str);
} catch (e) { }
}
var jsolait_baseURL = 'include/jsolait/lib';
var jsonrpc = jsonrpclite; //inline the module
//var jsonrpc = importModule("jsonrpclite");
// Root class of Sugar JS Application:
SugarClass.inherit("SugarContainer","SugarClass");
function SugarContainer(root_div)
{
GLOBAL_REGISTRY.container = this;
this.init(root_div);
}
SugarContainer.prototype.init = function(root_div) {
this.root_div = root_div;
SugarContainer.superclass.init.call(this);
}
SugarContainer.prototype.start = function(root_widget) {
this.root_widget = new root_widget();
this.root_widget.load(this.root_div);
}
var req_count = 0;
//////////////////////////////////////////////////
// class: SugarDateTime
// date and time utilities
//
//////////////////////////////////////////////////
SugarClass.inherit("SugarDateTime","SugarClass");
function SugarDateTime()
{
this.init(root_div);
}
SugarDateTime.prototype.init = function(root_div){
this.root_div = root_div;
}
// return the javascript Date object
// given the Sugar Meetings date_start/time_start or date_end/time_end
SugarDateTime.mysql2jsDateTime = function(mysql_date,mysql_time){
//var match = /(\d{4})-(\d{2})-(\d{2})/;
var match = new RegExp(date_reg_format);
if(((result= match.exec(mysql_date))) == null)
{
return null;
}
var match2 = new RegExp(time_reg_format);
// var match2 = /(\d{2}):(\d{2})/;
if((result2= match2.exec(mysql_time)) == null)
{
result2= [0,0,0,0];
}
var match3 = /^0(\d)/;
if((result3= match3.exec(result2[1])) != null)
{
result2[1] = result3[1];
}
if ( typeof (result2[3]) != 'undefined')
{
if ( result2[3] == 'pm' || result2[3] == 'PM')
{
if (parseInt( result2[1] ) != 12)
{
result2[1] = parseInt( result2[1] ) + 12;
}
}
else if ( result2[1] == 12 ) {
result2[1] = 0;
}
}
return new Date(result[date_reg_positions['Y']],result[date_reg_positions['m']] - 1,result[date_reg_positions['d']],result2[1],result2[2],0,0);
}
// make it a static func
// return the formatted day of the week of the date given a date object
SugarDateTime.prototype.getFormattedDate = function(date_obj) {
var returnDate = '';
var userDateFormat = GLOBAL_REGISTRY['current_user']['fields']['date_time_format']['date'];
var dow = GLOBAL_REGISTRY['calendar_strings']['dom_cal_weekdays_long'][date_obj.getDay()];
var month = date_obj.getMonth() + 1;
month = GLOBAL_REGISTRY['calendar_strings']['dom_cal_month_long'][month];
returnDate = dow;
for(i=0;i<5;i++) {
switch(userDateFormat.charAt(i)) {
case "Y":
returnDate += " " + date_obj.getFullYear();
break;
case "m":
returnDate += " " + month;
break;
case "d":
returnDate += " " + date_obj.getDate();
break;
default:
// cn: use locale's date separator? probably not.
//returnDate += " " + userDateFormat.charAt(i);
}
}
return returnDate;
//return dow+" "+date_obj.getDate()+" "+month+" "+date_obj.getFullYear();
}
SugarDateTime.getFormattedDate = SugarDateTime.prototype.getFormattedDate;
// return the formatted day of the week of the date given a date object
SugarDateTime.prototype.getFormattedDOW = function(date_obj) {
var hour = config.strings.mod_strings.Calendar.dow[date_obj.getDay()];
}
SugarDateTime.getFormattedDOW = SugarDateTime.prototype.getFormattedDOW;
// return the formatted hour of the date given a date object
SugarDateTime.getAMPM = function(date_obj) {
var hour = date_obj.getHour();
var am_pm = 'AM';
if (hour > 12)
{
hour -= 12;
am_pm = 'PM';
}
else if ( hour == 12)
{
am_pm = 'PM';
}
else if (hour == 0)
{
hour = 12;
}
return am_pm;
}
SugarDateTime.getFormattedHour = SugarDateTime.prototype.getFormattedHour;
//mod.SugarDateTime.getFormattedDate = publ.getFormattedDate;
// return the javascript Date object given a vCal UTC string
SugarDateTime.prototype.parseUTCDate = function(date_string) {
var match = /(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z/;
if(((result= match.exec(date_string))) != null)
{
var new_date = new Date(Date.UTC(result[1],result[2] - 1,result[3],result[4],result[5],parseInt(result[6])+time_offset));
return new_date;
}
}
SugarDateTime.parseUTCDate = SugarDateTime.prototype.parseUTCDate;
SugarDateTime.prototype.parseAdjustedDate = function(date_string, dst_start, dst_end, gmt_offset_secs) {
var match = /(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z/;
dst_start_parse = match.exec(dst_start);
dst_end_parse = match.exec(dst_end);
if(dst_start_parse == null || dst_end_parse == null) {
var new_date = new Date(result[1],result[2] - 1,result[3],result[4],result[5],parseInt(result[6]));
new_date = new Date(new_date.getTime() + gmt_offset_secs * 1000);
} else {
dst_start_obj = new Date(dst_start_parse[1],dst_start_parse[2] - 1,dst_start_parse[3],dst_start_parse[4],dst_start_parse[5],parseInt(dst_start_parse[6]));
dst_end_obj = new Date(dst_end_parse[1],dst_end_parse[2] - 1,dst_end_parse[3],dst_end_parse[4],dst_end_parse[5],parseInt(dst_end_parse[6]));
if(((result = match.exec(date_string))) != null)
{
var new_date = new Date(result[1],result[2] - 1,result[3],result[4],result[5],parseInt(result[6]));
var event_ts = new_date.getTime();
var dst_start_ts = dst_start_obj.getTime();
var dst_end_ts = dst_end_obj.getTime();
if(((event_ts >= dst_start_ts || event_ts < dst_end_ts) && dst_start_ts > dst_end_ts)
|| (event_ts >= dst_start_ts && event_ts < dst_end_ts)) {
new_date = new Date(new_date.getTime() + 60 * 60 * 1000);
}
new_date = new Date(new_date.getTime() + gmt_offset_secs * 1000);
}
}
return new_date;
}
SugarDateTime.parseAdjustedDate = SugarDateTime.prototype.parseAdjustedDate;
// create a hash based on a date
SugarDateTime.prototype.getUTCHash = function(startdate){
var month = ( startdate.getUTCMonth() < 10) ? "0"+startdate.getUTCMonth():""+startdate.getUTCMonth();
var day = ( startdate.getUTCDate() < 10) ? "0"+startdate.getUTCDate():""+startdate.getUTCDate();
var hours = ( startdate.getUTCHours() < 10) ? "0"+startdate.getUTCHours():""+startdate.getUTCHours();
var minutes = ( startdate.getUTCMinutes() < 10) ? "0"+startdate.getUTCMinutes():""+startdate.getUTCMinutes();
return startdate.getUTCFullYear()+month+day+hours+minutes;
return startdate.getUTCFullYear()+month+day+hours+minutes;
}
SugarDateTime.getUTCHash = SugarDateTime.prototype.getUTCHash;

View File

@@ -0,0 +1,536 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
var menuStack = new Array();
var hiddenElmStack = new Array();
var currentMenu = null;
var closeMenusDelay = null;
var openMenusDelay = null;
var delayTime = 75; // ms for menu open delay
function eraseTimeout(tId) {
//if (tId != null)
window.clearTimeout(tId);
return null;
}
function tbButtonMouseOverOrig(id){
closeMenusDelay = eraseTimeout(closeMenusDelay);
var menuName = id.replace(/Handle/i,'Menu');
var menu = getLayer(menuName);
//if (menu) menu.className = 'tbButtonMouseOverUp';
if (currentMenu){
closeAllMenus();
}
popupMenu(id, menu);
}
function tbButtonMouseOver(id,top,left,leftOffset){
closeMenusDelay = eraseTimeout(closeMenusDelay);
if (openMenusDelay == null){
openMenusDelay = window.setTimeout("showMenu('"+id+"','"+top+"','"+left+"','"+leftOffset+"')", delayTime);
}
}
function showMenu(id,top,left,leftOffset){
openMenusDelay = eraseTimeout(openMenusDelay);
var menuName = id.replace(/Handle/i,'Menu');
var menu = getLayer(menuName);
//if (menu) menu.className = 'tbButtonMouseOverUp';
if (currentMenu){
closeAllMenus();
}
popupMenu(id, menu, top,left,leftOffset);
}
function showSubMenu(id){
closeMenusDelay = eraseTimeout(closeMenusDelay);
var menuName = id.replace(/Handle/i,'Menu');
var menu = getLayer(menuName);
// if (currentMenu){
// closeMenus();
// }
// popupMenu(id, menu);
popupSubMenu(id, menu);
}
function popupMenu(handleID, menu, top, left, leftOffset){
var bw = checkBrowserWidth();
var menuName = handleID.replace(/Handle/i,'Menu');
var menuWidth = 120;
var imgWidth = document.getElementById(handleID).width;
if (menu){
var menuHandle = getLayer(handleID);
var p=menuHandle;
if (left == "") {
var left = 0;
while(p&&p.tagName.toUpperCase()!='BODY'){
left+=p.offsetLeft;
p=p.offsetParent;
}
left+=parseInt(leftOffset);
}
if (left+menuWidth>bw) {
left = left-menuWidth+imgWidth;
}
setMenuVisible(menu, left, top, false);
}
}
function popupSubMenu(handleID, menu){
if (menu){
var menuHandle = getLayer(handleID);
var p=menuHandle;
//var top = p.offsetHeight, left = 0;
var top = 0, left = p.offsetWidth;
while(p&&p.tagName.toUpperCase()!='BODY'){
top+=p.offsetTop;
left+=p.offsetLeft;
p=p.offsetParent;
}
if (is.ie && is.mac){
top -= 3;
left -= 10;
}
/*
if (menu.isSubMenu){
try{
if (blnNetscape6){
left+=(getLayer(menu.parentid).offsetWidth - 4);
}else{
left+=(getLayer(menu.parentid).clientWidth - 8);
}
}catch(e){
}
}else{
top += menuItem.offsetHeight;
}
*/
//menu.x = left;
//menu.y = top;
setMenuVisible(menu, left, top, true);
//fixWidth(paneID, menu);
}
}
function closeMenusOrig(){
if (currentMenu){
setMenuVisibility(currentMenu, false);
// currentMenu = null;
}
}
function closeSubMenus(handle){
closeMenusDelay = eraseTimeout(closeMenusDelay);
if (menuStack.length > 0){
for (var i = menuStack.length-1; i >=0; i--){
var menu = menuStack[menuStack.length-1];
if (menu.id == handle.getAttribute('parentid')){
currentMenu = menu;
break;
}else{
closeMenu(menu);
//menuStack.pop();
menuPop();
}
}
}
}
function closeMenu(menu){
setMenuVisibility(menu, false);
}
function closeMenusOrig(){
if (menuStack.length > 0){
for (var i = menuStack.length-1; i >=0; i--){
//var menu = menuStack.pop();
var menu = menuPop();
closeMenu(menu);
}
}
currentMenu = null;
}
function closeMenus(){
if (closeMenusDelay == null){
closeMenusDelay = window.setTimeout("closeAllMenus()", delayTime);
}
}
function closeAllMenus(){
closeMenusDelay = eraseTimeout(closeMenusDelay);
if (menuStack.length > 0){
for (var i = menuStack.length-1; i >=0; i--){
//var menu = menuStack.pop();
var menu = menuPop();
closeMenu(menu);
}
}
currentMenu = null;
}
function setMenuVisible(menu, x, y, isSubMenu){
/*
var id = menu.id;
var left=0;
var top=0;
var menuItem = menu.getMenuItemElm();
if (menuItem && menu){
if (menu.isTopMenu){
menuItem.className = 'tbButtonMouseDown';
}
}
*/
if (menu){
//menu.x = left;
//menu.y = top;
if (isSubMenu){
if (menu.getAttribute('parentid') == currentMenu.getAttribute('parentid')){
//menuStack.pop();
menuPop();
setMenuVisibility(currentMenu, false);
}
}else{
//menuStack.pop();
menuPop();
setMenuVisibility(currentMenu, false);
}
currentMenu = menu;
//menuStack.push(menu);
menuPush(menu);
setMenuVisibility(menu, true, x, y);
}
}
function getLayer(layerid){
/*
if (document.layers && layerid){
if (document.layers[layerid]) return document.layers[layerid];
}
if (document.links && layerid){
if (document.links[layerid]) return document.links[layerid];
}
if (document.all && layerid){
if (document.all(layerid)) return document.all(layerid);
}
*/
return document.getElementById(layerid);
}
function setMenuVisibility(menu, on, x, y){
var parent = menu;
if (menu){
/*
menu.visible = on;
setLayer(menu.id, !menu.visible, menu.x, menu.y);
setLayer(menu.id, !menu.visible, 0, 0);
menu.visible = on;
*/
setLayer(menu.id, !on, x, y);
if (is.ie){
if (!on){
if (!menu.getAttribute('parentid')){
showElement("SELECT");
}
}else{
hideElement("SELECT", x, y, menu.offsetWidth, menu.offsetHeight);
}
}
/*
setLayer(menu.id, !menu.visible, 0, 0);
var menuWidth, menuHeight;
var menuLayer = getLayer(menu.id);
if (menuLayer){
if (blnIE55){
menuWidth = menuLayer.clientWidth;
menuHeight = menuLayer.clientHeight;
}else{
menuWidth = menuLayer.offsetWidth;
menuHeight = menuLayer.offsetHeight;
}
if (menu.x+menuWidth > clientWindowWidth){
menu.x = clientWindowWidth - menuWidth - 25;
if (menu.x < 10){
menu.x = 10;
}
}
if (menu.y+menuHeight > clientWindowHeight){
menu.y = clientWindowHeight - menuHeight - 25;
if (menu.y < 10){
menu.y = 10;
}
}
setLayer(menu.id, !menu.visible, menu.x, menu.y);
}
*/
}
/*
var parentid = menu.parentid;
while (parentid){
parent = getMenu(menu.paneID, parentid);
if (parent){
parent.visible = on;
setLayer(parent.id, !parent.visible, parent.x, parent.y);
parentid = parent.parentid;
if (on == false) currentMenu = parent;
}else{
parentid = null;
}
}
}
return parent;
*/
}
function menuPop(){
if (is.ie && (is.mac || !is.ie5_5up)){
var menu = menuStack[menuStack.length-1];
var newMenuStack = new Array();
for (var i = 0; i < menuStack.length-1; i++){
newMenuStack[newMenuStack.length] = menuStack[i];
}
menuStack = newMenuStack;
return menu;
}else{
return menuStack.pop();
}
}
function menuPush(menu){
if (is.ie && (is.mac || !is.ie5_5up)){
menuStack[menuStack.length] = menu;
}else{
menuStack.push(menu);
}
}
function checkBrowserWidth(){
var windowWidth;
if (is.ie){
windowWidth = document.body.clientWidth;
}else{
// 17px for scrollbar width
windowWidth = window.innerWidth - 16;
}
if (windowWidth >= 1000){
showSB('sbContent',true,'sb');
}else{
showSB('sbContent',false,'sb');
}
return windowWidth;
}
function showSB(id, hideit, imgIdPrefix){
setLayer(id, !hideit, -1, -1);
setLayer(imgIdPrefix+'On', !hideit, -1, -1);
setLayer(imgIdPrefix+'Off', hideit, -1, -1);
}
function setLayer(id, hidden, x, y){
var layer = getLayer(id);
setLayerElm(layer, hidden, x, y);
}
function setLayerElm(layer, hideit, x, y){
if (layer && layer.style){
if (hideit){
layer.style.visibility='hidden';
//layer.style.display='none';
}else{
layer.style.display='block';
layer.style.visibility='visible';
}
if (x >=0 && x != ""){
//alert(layer.id+': '+x+', '+y+'\n'+layer.offsetLeft+', '+layer.offsetTop);
//layer.style.left=x;
//layer.style.top=y;
layer.style.left = x+'px';
}
if (y >= 0 && y != "") {
layer.style.top = y+'px';
}
}
}
function hiliteItem(menuItem,changeClass){
closeMenusDelay = eraseTimeout(closeMenusDelay);
if (changeClass=='yes') {
if (menuItem.getAttribute('avid') == 'false'){
menuItem.className = 'menuItemHiliteX';
}else{
menuItem.className = 'menuItemHilite';
}
}
}
function unhiliteItem(menuItem){
closeMenusDelay = eraseTimeout(closeMenusDelay);
if (menuItem.getAttribute('avid') == 'false'){
menuItem.className = 'menuItemX';
}else{
menuItem.className = 'menuItem';
}
}
function showElement(elmID){
for (i = 0; i < document.getElementsByTagName(elmID).length; i++) {
obj = document.getElementsByTagName(elmID)[i];
if (! obj || ! obj.offsetParent)
continue;
obj.style.visibility = "";
}
}
function showElementNew(elmID){
if (hiddenElmStack.length > 0){
for (var i = hiddenElmStack.length-1; i >=0; i--){
var obj = hiddenElmStack[hiddenElmStack.length-1];
obj.style.visibility = "";;
hiddenElmStack.pop();
}
}
}
function hideElement(elmID,x,y,w,h){
for (i = 0; i < document.getElementsByTagName(elmID).length; i++){
obj = document.getElementsByTagName(elmID)[i];
if (! obj || ! obj.offsetParent)
continue;
// Find the element's offsetTop and offsetLeft relative to the BODY tag.
objLeft = obj.offsetLeft;
objTop = obj.offsetTop;
objParent = obj.offsetParent;
while (objParent.tagName.toUpperCase() != "BODY"){
objLeft += objParent.offsetLeft;
objTop += objParent.offsetTop;
if(objParent.offsetParent == null)
break;
else
objParent = objParent.offsetParent;
}
// Adjust the element's offsetTop relative to the dropdown menu
objTop = objTop - y;
if (x > (objLeft + obj.offsetWidth) || objLeft > (x + w))
;
else if (objTop > h)
;
else if ((y + h) <= 80)
;
else {
obj.style.visibility = "hidden";
//hiddenElmStack.push(obj);
}
}
}
function Is (){
// convert all characters to lowercase to simplify testing
var agt = navigator.userAgent.toLowerCase();
// *** BROWSER VERSION ***
// Note: On IE5, these return 4, so use is.ie5up to detect IE5.
this.major = parseInt(navigator.appVersion);
this.minor = parseFloat(navigator.appVersion);
// Note: Opera and WebTV spoof Navigator. We do strict client detection.
// If you want to allow spoofing, take out the tests for opera and webtv.
this.nav = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
&& (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
&& (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1));
this.nav2 = (this.nav && (this.major == 2));
this.nav3 = (this.nav && (this.major == 3));
this.nav4 = (this.nav && (this.major == 4));
this.nav4up = (this.nav && (this.major >= 4));
this.navonly = (this.nav && ((agt.indexOf(";nav") != -1) ||
(agt.indexOf("; nav") != -1)) );
this.nav6 = (this.nav && (this.major == 5));
this.nav6up = (this.nav && (this.major >= 5));
this.gecko = (agt.indexOf('gecko') != -1);
this.nav7 = (this.gecko && (this.major >= 5) && (agt.indexOf('netscape/7')!=-1));
this.moz1 = false;
this.moz1up = false;
this.moz1_1 = false;
this.moz1_1up = false;
if (this.nav6up){
// if (this.nav){
myRegEx = new RegExp("rv:\\d*.\\d*.\\d*");
//myFind = myRegEx.exec("; rv:9.10.5)");
myFind = myRegEx.exec(agt);
if(myFind!=null){
var strVersion = myFind.toString();
strVersion = strVersion.replace(/rv:/,'');
var arrVersion = strVersion.split('.');
var major = parseInt(arrVersion[0]);
var minor = parseInt(arrVersion[1]);
if (arrVersion[2]) var revision = parseInt(arrVersion[2]);
this.moz1 = ((major == 1) && (minor == 0));
this.moz1up = ((major == 1) && (minor >= 0));
this.moz1_1 = ((major == 1) && (minor == 1));
this.moz1_1up = ((major == 1) && (minor >= 1));
}
}
this.ie = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
this.ie3 = (this.ie && (this.major < 4));
this.ie4 = (this.ie && (this.major == 4) && (agt.indexOf("msie 4")!=-1) );
this.ie4up = (this.ie && (this.major >= 4));
this.ie5 = (this.ie && (this.major == 4) && (agt.indexOf("msie 5.0")!=-1) );
this.ie5_5 = (this.ie && (this.major == 4) && (agt.indexOf("msie 5.5") !=-1));
this.ie5up = (this.ie && !this.ie3 && !this.ie4);
this.ie5_5up =(this.ie && !this.ie3 && !this.ie4 && !this.ie5);
this.ie6 = (this.ie && (this.major == 4) && (agt.indexOf("msie 6.")!=-1) );
this.ie6up = (this.ie && !this.ie3 && !this.ie4 && !this.ie5 && !this.ie5_5);
this.mac = (agt.indexOf("mac") != -1);
}
function runPageLoadItems (){
var myVar;
checkBrowserWidth();
}
var is = new Is();
if (is.ie) {
document.write('<style type="text/css">');
document.write('body {font-size: x-small;}');
document.write ('</style>');
}

View File

@@ -0,0 +1,782 @@
/*
Artistic License 2.0
Copyright (c) 2000-2006, The Perl Foundation.
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software.
You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement.
Definitions
"Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package.
"Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures.
"You" and "your" means any person who would like to copy, distribute, or modify the Package.
"Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version.
"Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization.
"Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees.
"Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder.
"Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder.
"Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future.
"Source" form means the source code, documentation source, and configuration files for the Package.
"Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form.
Permission for Use and Modification Without Distribution
(1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version.
Permissions for Redistribution of the Standard Version
(2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package.
(3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License.
Distribution of Modified Versions of the Package as Source
(4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following:
(a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version.
(b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version.
(c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under
(i) the Original License or
(ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed.
Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source
(5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license.
(6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version.
Aggregating or Linking the Package
(7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation.
(8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package.
Items That are Not Considered Part of a Modified Version
(9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license.
General Provisions
(10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.
(11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.
(12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.
(13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.
(14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
Do not remove or change this notice.
overlibmws.js core module - Copyright Foteos Macrides 2002-2005. All rights reserved.
Initial: August 18, 2002 - Last Revised: June 8, 2005
This module is subject to the same terms of usage as for Erik Bosrup's overLIB,
though only a minority of the code and API now correspond with Erik's version.
See the overlibmws Change History and Command Reference via:
http://www.macridesweb.com/oltest/
Published under an open source license: http://www.macridesweb.com/oltest/license.html
Give credit on sites that use overlibmws and submit changes so others can use them as well.
You can get Erik's version via: http://www.bosrup.com/web/overlib/
* The name of the Copyright Holder may not be used to endorse or promote products derived
from this software without specific prior written permission.
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
A PARTICULAR PURPOSE.
*/
// PRE-INIT -- Ignore these lines, configuration is below.
var OLloaded=0,pmCnt=1,pMtr=new Array(),OLcmdLine=new Array(),OLrunTime=new Array(),OLv,OLudf,
OLpct=new Array("83%","67%","83%","100%","117%","150%","200%","267%"),OLrefXY,
OLbubblePI=0,OLcrossframePI=0,OLdebugPI=0,OLdraggablePI=0,OLexclusivePI=0,OLfilterPI=0,
OLfunctionPI=0,OLhidePI=0,OLiframePI=0,OLovertwoPI=0,OLscrollPI=0,OLshadowPI=0,OLprintPI=0;
if(typeof OLgateOK=='undefined')var OLgateOK=1;
var OLp1or2c='inarray,caparray,caption,closetext,right,left,center,autostatuscap,padx,pady,'
+'below,above,vcenter,donothing',OLp1or2co='nofollow,background,offsetx,offsety,fgcolor,'
+'bgcolor,cgcolor,textcolor,capcolor,width,wrap,wrapmax,height,border,base,status,autostatus,'
+'snapx,snapy,fixx,fixy,relx,rely,midx,midy,ref,refc,refp,refx,refy,fgbackground,bgbackground,'
+'cgbackground,fullhtml,capicon,textfont,captionfont,textsize,captionsize,timeout,delay,hauto,'
+'vauto,nojustx,nojusty,fgclass,bgclass,cgclass,capbelow,textpadding,textfontclass,'
+'captionpadding,captionfontclass,sticky,noclose,mouseoff,offdelay,closecolor,closefont,'
+'closesize,closeclick,closetitle,closefontclass,decode',OLp1or2o='text,cap,close,hpos,vpos,'
+'padxl,padxr,padyt,padyb',OLp1co='label',OLp1or2=OLp1or2co+','+OLp1or2o,OLp1=OLp1co+','+'frame';
OLregCmds(OLp1or2c+','+OLp1or2co+','+OLp1co);
function OLud(v){return eval('typeof ol_'+v+'=="undefined"')?1:0;}
// DEFAULT CONFIGURATION -- See overlibConfig.txt for descriptions
if(OLud('fgcolor'))var ol_fgcolor="#ccccff";
if(OLud('bgcolor'))var ol_bgcolor="#333399";
if(OLud('cgcolor'))var ol_cgcolor="#333399";
if(OLud('textcolor'))var ol_textcolor="#000000";
if(OLud('capcolor'))var ol_capcolor="#ffffff";
if(OLud('closecolor'))var ol_closecolor="#eeeeff";
if(OLud('textfont'))var ol_textfont="Verdana,Arial,Helvetica";
if(OLud('captionfont'))var ol_captionfont="Verdana,Arial,Helvetica";
if(OLud('closefont'))var ol_closefont="Verdana,Arial,Helvetica";
if(OLud('textsize'))var ol_textsize=1;
if(OLud('captionsize'))var ol_captionsize=1;
if(OLud('closesize'))var ol_closesize=1;
if(OLud('fgclass'))var ol_fgclass="";
if(OLud('bgclass'))var ol_bgclass="";
if(OLud('cgclass'))var ol_cgclass="";
if(OLud('textpadding'))var ol_textpadding=2;
if(OLud('textfontclass'))var ol_textfontclass="";
if(OLud('captionpadding'))var ol_captionpadding=2;
if(OLud('captionfontclass'))var ol_captionfontclass="";
if(OLud('closefontclass'))var ol_closefontclass="";
if(OLud('close'))var ol_close="Close";
if(OLud('closeclick'))var ol_closeclick=0;
if(OLud('closetitle'))var ol_closetitle="Click to Close";
if(OLud('text'))var ol_text="Default Text";
if(OLud('cap'))var ol_cap="";
if(OLud('capbelow'))var ol_capbelow=0;
if(OLud('background'))var ol_background="";
if(OLud('width'))var ol_width=200;
if(OLud('wrap'))var ol_wrap=0;
if(OLud('wrapmax'))var ol_wrapmax=0;
if(OLud('height'))var ol_height= -1;
if(OLud('border'))var ol_border=1;
if(OLud('base'))var ol_base=0;
if(OLud('offsetx'))var ol_offsetx=10;
if(OLud('offsety'))var ol_offsety=10;
if(OLud('sticky'))var ol_sticky=0;
if(OLud('nofollow'))var ol_nofollow=0;
if(OLud('noclose'))var ol_noclose=0;
if(OLud('mouseoff'))var ol_mouseoff=0;
if(OLud('offdelay'))var ol_offdelay=300;
if(OLud('hpos'))var ol_hpos=RIGHT;
if(OLud('vpos'))var ol_vpos=BELOW;
if(OLud('status'))var ol_status="";
if(OLud('autostatus'))var ol_autostatus=0;
if(OLud('snapx'))var ol_snapx=0;
if(OLud('snapy'))var ol_snapy=0;
if(OLud('fixx'))var ol_fixx= -1;
if(OLud('fixy'))var ol_fixy= -1;
if(OLud('relx'))var ol_relx=null;
if(OLud('rely'))var ol_rely=null;
if(OLud('midx'))var ol_midx=null;
if(OLud('midy'))var ol_midy=null;
if(OLud('ref'))var ol_ref="";
if(OLud('refc'))var ol_refc='UL';
if(OLud('refp'))var ol_refp='UL';
if(OLud('refx'))var ol_refx=0;
if(OLud('refy'))var ol_refy=0;
if(OLud('fgbackground'))var ol_fgbackground="";
if(OLud('bgbackground'))var ol_bgbackground="";
if(OLud('cgbackground'))var ol_cgbackground="";
if(OLud('padxl'))var ol_padxl=1;
if(OLud('padxr'))var ol_padxr=1;
if(OLud('padyt'))var ol_padyt=1;
if(OLud('padyb'))var ol_padyb=1;
if(OLud('fullhtml'))var ol_fullhtml=0;
if(OLud('capicon'))var ol_capicon="";
if(OLud('frame'))var ol_frame=self;
if(OLud('timeout'))var ol_timeout=0;
if(OLud('delay'))var ol_delay=0;
if(OLud('hauto'))var ol_hauto=0;
if(OLud('vauto'))var ol_vauto=0;
if(OLud('nojustx'))var ol_nojustx=0;
if(OLud('nojusty'))var ol_nojusty=0;
if(OLud('label'))var ol_label="";
if(OLud('decode'))var ol_decode=0;
// ARRAY CONFIGURATION - See overlibConfig.txt for descriptions.
if(OLud('texts'))var ol_texts=new Array("Text 0","Text 1");
if(OLud('caps'))var ol_caps=new Array("Caption 0","Caption 1");
// END CONFIGURATION -- Don't change anything below, all configuration is above.
// INIT -- Runtime variables.
var o3_text="",o3_cap="",o3_sticky=0,o3_nofollow=0,o3_background="",o3_noclose=0,o3_mouseoff=0,
o3_offdelay=300,o3_hpos=RIGHT,o3_offsetx=10,o3_offsety=10,o3_fgcolor="",o3_bgcolor="",
o3_cgcolor="",o3_textcolor="",o3_capcolor="",o3_closecolor="",o3_width=200,o3_wrap=0,
o3_wrapmax=0,o3_height= -1,o3_border=1,o3_base=0,o3_status="",o3_autostatus=0,o3_snapx=0,
o3_snapy=0,o3_fixx= -1,o3_fixy= -1,o3_relx=null,o3_rely=null,o3_midx=null,o3_midy=null,o3_ref="",
o3_refc='UL',o3_refp='UL',o3_refx=0,o3_refy=0,o3_fgbackground="",o3_bgbackground="",
o3_cgbackground="",o3_padxl=0,o3_padxr=0,o3_padyt=0,o3_padyb=0,o3_fullhtml=0,o3_vpos=BELOW,
o3_capicon="",o3_textfont="Verdana,Arial,Helvetica",o3_captionfont="",o3_closefont="",
o3_textsize=1,o3_captionsize=1,o3_closesize=1,o3_frame=self,o3_timeout=0,o3_delay=0,o3_hauto=0,
o3_vauto=0,o3_nojustx=0,o3_nojusty=0,o3_close="",o3_closeclick=0,o3_closetitle="",o3_fgclass="",
o3_bgclass="",o3_cgclass="",o3_textpadding=2,o3_textfontclass="",o3_captionpadding=2,
o3_captionfontclass="",o3_closefontclass="",o3_capbelow=0,o3_label="",o3_decode=0,
CSSOFF=DONOTHING,CSSCLASS=DONOTHING,OLdelayid=0,OLtimerid=0,OLshowid=0,OLndt=0,over=null,
OLfnRef="",OLhover=0,OLx=0,OLy=0,OLshowingsticky=0,OLallowmove=0,OLcC=null,
OLua=navigator.userAgent.toLowerCase(),
OLns4=(navigator.appName=='Netscape'&&parseInt(navigator.appVersion)==4),
OLns6=(document.getElementById)?1:0,
OLie4=(document.all)?1:0,
OLgek=(OLv=OLua.match(/gecko\/(\d{8})/i))?parseInt(OLv[1]):0,
OLmac=(OLua.indexOf('mac')>=0)?1:0,
OLsaf=(OLua.indexOf('safari')>=0)?1:0,
OLkon=(OLua.indexOf('konqueror')>=0)?1:0,
OLkht=(OLsaf||OLkon)?1:0,
OLopr=(OLua.indexOf('opera')>=0)?1:0,
OLop7=(OLopr&&document.createTextNode)?1:0;
if(OLopr){OLns4=OLns6=0;if(!OLop7)OLie4=0;}
var OLieM=((OLie4&&OLmac)&&!(OLkht||OLopr))?1:0,
OLie5=0,OLie55=0;if(OLie4&&!OLop7){
if((OLv=OLua.match(/msie (\d\.\d+)\.*/i))&&(OLv=parseFloat(OLv[1]))>=5.0){
OLie5=1;OLns6=0;if(OLv>=5.5)OLie55=1;}if(OLns6)OLie4=0;}
if(OLns4)window.onresize=function(){location.reload();}
var OLchkMh=1,OLdw;
if(OLns4||OLie4||OLns6)OLmh();
else{overlib=nd=cClick=OLpageDefaults=no_overlib;}
/*
PUBLIC FUNCTIONS
*/
// Loads defaults then args into runtime variables.
function overlib(){
if(!(OLloaded&&OLgateOK))return;
if((OLexclusivePI)&&OLisExclusive(arguments))return true;
if(OLchkMh)OLmh();
if(OLndt&&!OLtimerid)OLndt=0;if(over)cClick();
OLload(OLp1or2);OLload(OLp1);
OLfnRef="";OLhover=0;
OLsetRunTimeVar();
OLparseTokens('o3_',arguments);
if(!(over=OLmkLyr()))return false;
if(o3_decode)OLdecode();
if(OLprintPI)OLchkPrint();
if(OLbubblePI)OLchkForBubbleEffect();
if(OLdebugPI)OLsetDebugCanShow();
if(OLshadowPI)OLinitShadow();
if(OLiframePI)OLinitIfs();
if(OLfilterPI)OLinitFilterLyr();
if(OLexclusivePI&&o3_exclusive&&o3_exclusivestatus!="")o3_status=o3_exclusivestatus;
else if(o3_autostatus==2&&o3_cap!="")o3_status=o3_cap;
else if(o3_autostatus==1&&o3_text!="")o3_status=o3_text;
if(!o3_delay){return OLmain();
}else{OLdelayid=setTimeout("OLmain()",o3_delay);
if(o3_status!=""){self.status=o3_status;return true;}
else if(!(OLop7&&event&&event.type=='mouseover'))return false;}
}
// Clears popups if appropriate
function nd(time){
if(OLloaded&&OLgateOK){if(!((OLexclusivePI)&&OLisExclusive())){
if(time&&over&&!o3_delay){if(OLtimerid>0)clearTimeout(OLtimerid);
OLtimerid=(OLhover&&o3_frame==self&&!OLcursorOff())?0:
setTimeout("cClick()",(o3_timeout=OLndt=time));}else{
if(!OLshowingsticky){OLallowmove=0;if(over)OLhideObject(over);}}}}
return false;
}
// Close function for stickies
function cClick(){
if(OLloaded&&OLgateOK){OLhover=0;if(over){
if(OLovertwoPI&&over==over2)cClick2();OLhideObject(over);OLshowingsticky=0;}}
return false;
}
// Sets page-specific defaults.
function OLpageDefaults(){
OLparseTokens('ol_',arguments);
}
// For unsupported browsers.
function no_overlib(){return false;}
/*
OVERLIB MAIN FUNCTION SET
*/
function OLmain(){
o3_delay=0;
if(o3_frame==self){if(o3_noclose)OLoptMOUSEOFF(0);else if(o3_mouseoff)OLoptMOUSEOFF(1);}
if(o3_sticky)OLshowingsticky=1;OLdoLyr();OLallowmove=0;if(o3_timeout>0){
if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=setTimeout("cClick()",o3_timeout);}
if(o3_ref){OLrefXY=OLgetRefXY(o3_ref);if(OLrefXY[0]==null){o3_ref="";o3_midx=0;o3_midy=0;}}
OLdisp(o3_status);if(OLdraggablePI)OLcheckDrag();
if(o3_status!="")return true;else if(!(OLop7&&event&&event.type=='mouseover'))return false;
}
// Loads o3_ variables
function OLload(c){var i,m=c.split(',');for(i=0;i<m.length;i++)eval('o3_'+m[i]+'=ol_'+m[i]);}
// Chooses LGF
function OLdoLGF(){
return (o3_background!=''||o3_fullhtml)?OLcontentBackground(o3_text,o3_background,o3_fullhtml):
(o3_cap=="")?OLcontentSimple(o3_text):
(o3_sticky)?OLcontentCaption(o3_text,o3_cap,o3_close):OLcontentCaption(o3_text,o3_cap,'');
}
// Makes Layer
function OLmkLyr(id,f,z){
id=(id||'overDiv');f=(f||o3_frame);z=(z||1000);var fd=f.document,d=OLgetRefById(id,fd);
if(!d){if(OLns4)d=fd.layers[id]=new Layer(1024,f);else if(OLie4&&!document.getElementById){
fd.body.insertAdjacentHTML('BeforeEnd','<div id="'+id+'"></div>');d=fd.all[id];
}else{d=fd.createElement('div');if(d){d.id=id;fd.body.appendChild(d);}}if(!d)return null;
if(OLns4)d.zIndex=z;else{var o=d.style;o.position='absolute';o.visibility='hidden';o.zIndex=z;}}
return d;
}
// Creates and writes layer content
function OLdoLyr(){
if(o3_background==''&&!o3_fullhtml){
if(o3_fgbackground!='')o3_fgbackground=' background="'+o3_fgbackground+'"';
if(o3_bgbackground!='')o3_bgbackground=' background="'+o3_bgbackground+'"';
if(o3_cgbackground!='')o3_cgbackground=' background="'+o3_cgbackground+'"';
if(o3_fgcolor!='')o3_fgcolor=' bgcolor="'+o3_fgcolor+'"';
if(o3_bgcolor!='')o3_bgcolor=' bgcolor="'+o3_bgcolor+'"';
if(o3_cgcolor!='')o3_cgcolor=' bgcolor="'+o3_cgcolor+'"';
if(o3_height>0)o3_height=' height="'+o3_height+'"';else o3_height='';}
if(!OLns4)OLrepositionTo(over,(OLns6?20:0),0);var lyrHtml=OLdoLGF();
if(o3_sticky&&OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}
if(o3_wrap&&!o3_fullhtml){OLlayerWrite(lyrHtml);
o3_width=(OLns4?over.clip.width:over.offsetWidth);
if(OLns4&&o3_wrapmax<1)o3_wrapmax=o3_frame.innerWidth-40;
o3_wrap=0;if(o3_wrapmax>0&&o3_width>o3_wrapmax)o3_width=o3_wrapmax;lyrHtml=OLdoLGF();}
OLlayerWrite(lyrHtml);o3_width=(OLns4?over.clip.width:over.offsetWidth);
if(OLbubblePI)OLgenerateBubble(lyrHtml);
}
/*
LAYER GENERATION FUNCTIONS
*/
// Makes simple table without caption
function OLcontentSimple(txt){
var t=OLbgLGF()+OLfgLGF(txt)+OLbaseLGF();
OLsetBackground('');return t;
}
// Makes table with caption and optional close link
function OLcontentCaption(txt,title,close){
var closing=(OLprintPI?OLprintCapLGF():''),closeevent='onmouseover',caption,t,
cC='javascript:return '+OLfnRef+(OLovertwoPI&&over==over2?'cClick2();':'cClick();');
if(o3_closeclick)closeevent=(o3_closetitle?'title="'+o3_closetitle+'" ':'')+'onclick';
if(o3_capicon!='')o3_capicon='<img src="'+o3_capicon+'" /> ';
if(close){closing+='<a href="'+cC+'" '
+closeevent+'="'+cC+'"'+(o3_closefontclass?'>':'>'+OLlgfUtil(0,'','span',o3_closecolor,o3_closefont,o3_closesize))+close
+(o3_closefontclass?'':OLlgfUtil(1,'','span'))+'</a>';}
caption='<table'+OLwd(0)+' border="0" cellpadding="'+o3_captionpadding+'" cellspacing="0"'
+(o3_cgclass?' class="'+o3_cgclass+'"':o3_cgcolor+o3_cgbackground)+'><tr><td'+OLwd(0)
+(o3_cgclass?' class="'+o3_cgclass+'">':'>')+(o3_captionfontclass?'<div class="'
+o3_captionfontclass+'">':''
+OLlgfUtil(0,'','',o3_capcolor,o3_captionfont,o3_captionsize))+o3_capicon+title
+OLlgfUtil(1,'','')+(o3_captionfontclass?'':'')+closing+'</div></td></tr></table>';
t=OLbgLGF()+(o3_capbelow?OLfgLGF(txt)+caption:caption+OLfgLGF(txt))+OLbaseLGF();
OLsetBackground('');return t;
}
// For BACKGROUND and FULLHTML commands
function OLcontentBackground(txt, image, hasfullhtml){
var t;if(hasfullhtml){t=txt;}else{t='<table'+OLwd(1)
+' border="0" cellpadding="0" cellspacing="0" '+'height="'+o3_height
+'"><tr><td colspan="3" height="'+o3_padyt+'"></td></tr><tr><td width="'
+o3_padxl+'"></td><td valign="top"'+OLwd(2)+'>'
+OLlgfUtil(0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+txt+
OLlgfUtil(1,'','div')+'</td><td width="'+o3_padxr+'"></td></tr><tr><td colspan="3" height="'
+o3_padyb+'"></td></tr></table>';}
OLsetBackground(image);return t;
}
// LGF utilities
function OLbgLGF(){
return '<table'+OLwd(1)+o3_height+' border="0" cellpadding="'+o3_border+'" cellspacing="0"'
+(o3_bgclass?' class="'+o3_bgclass+'"':o3_bgcolor+o3_bgbackground)+'><tr><td>';
}
function OLfgLGF(t){
return '<table'+OLwd(0)+o3_height+' border="0" cellpadding="'+o3_textpadding
+'" cellspacing="0"'+(o3_fgclass?' class="'+o3_fgclass+'"':o3_fgcolor+o3_fgbackground)
+'><tr><td valign="top"'+(o3_fgclass?' class="'+o3_fgclass+'"':'')+'>'
+OLlgfUtil(0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+t
+(OLprintPI?OLprintFgLGF():'')+OLlgfUtil(1,'','div')+'</td></tr></table>';
}
function OLlgfUtil(end,tfc,ele,col,fac,siz){
if(end)return ('</'+(OLns4?'font':ele)+'>');else return (tfc?'<div class="'+tfc+'">':
('<'+(OLns4?'font color="'+col+'" face="'+OLquoteMultiNameFonts(fac)+'" size="'+siz:ele
+' style="color:'+col+';font-family:'+OLquoteMultiNameFonts(fac)+';font-size:'+siz+';'
+(ele=='span'?'text-decoration:underline;':''))+'">'));
}
function OLquoteMultiNameFonts(f){
var i,v,pM=f.split(',');
for(i=0;i<pM.length;i++){v=pM[i];v=v.replace(/^\s+/,'').replace(/\s+$/,'');
if(/\s/.test(v) && !/['"]/.test(v)){v="\'"+v+"\'";pM[i]=v;}} //' extra quote is added for minification work around
return pM.join();
}
function OLbaseLGF(){
return ((o3_base>0&&!o3_wrap)?('<table width="100%" border="0" cellpadding="0" cellspacing="0"'
+(o3_bgclass?' class="'+o3_bgclass+'"':'')+'><tr><td height="'+o3_base
+'"></td></tr></table>'):'')+'</td></tr></table>';
}
function OLwd(a){
return(o3_wrap?'':' width="'+(!a?'100%':(a==1?o3_width:(o3_width-o3_padxl-o3_padxr)))+'"');
}
// Loads image into the div.
function OLsetBackground(i){
if(i==''){if(OLns4)over.background.src=null;
else{if(OLns6)over.style.width='';over.style.backgroundImage='none';}
}else{if(OLns4)over.background.src=i;
else{if(OLns6)over.style.width=o3_width+'px';over.style.backgroundImage='url('+i+')';}}
}
/*
HANDLING FUNCTIONS
*/
// Displays layer
function OLdisp(s){
if(!OLallowmove){if(OLshadowPI)OLdispShadow();if(OLiframePI)OLdispIfs();OLplaceLayer();
if(OLndt)OLshowObject(over);else OLshowid=setTimeout("OLshowObject(over)",1);
OLallowmove=(o3_sticky||o3_nofollow)?0:1;}OLndt=0;if(s!="")self.status=s;
}
// Decides placement of layer.
function OLplaceLayer(){
var snp,X,Y,pgLeft,pgTop,pWd=o3_width,pHt,iWd=100,iHt=100,SB=0,LM=0,CX=0,TM=0,BM=0,CY=0,
o=OLfd(),nsb=(OLgek>=20010505&&!o3_frame.scrollbars.visible)?1:0;
if(!OLkht&&o&&o.clientWidth)iWd=o.clientWidth;
else if(o3_frame.innerWidth){SB=Math.ceil(1.4*(o3_frame.outerWidth-o3_frame.innerWidth));
if(SB>20)SB=20;iWd=o3_frame.innerWidth;}
pgLeft=(OLie4)?o.scrollLeft:o3_frame.pageXOffset;
if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)SB=CX=5;else
if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){SB+=((o3_shadowx>0)?o3_shadowx:0);
LM=((o3_shadowx<0)?Math.abs(o3_shadowx):0);CX=Math.abs(o3_shadowx);}
if(o3_ref!=""||o3_fixx> -1||o3_relx!=null||o3_midx!=null){
if(o3_ref!=""){X=OLrefXY[0];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){
if(o3_refp=='UR'||o3_refp=='LR')X-=5;}
else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){
if(o3_shadowx<0&&(o3_refp=='UL'||o3_refp=='LL'))X-=o3_shadowx;else
if(o3_shadowx>0&&(o3_refp=='UR'||o3_refp=='LR'))X-=o3_shadowx;}
}else{if(o3_midx!=null){
X=parseInt(pgLeft+((iWd-pWd-SB-LM)/2)+o3_midx);
}else{if(o3_relx!=null){
if(o3_relx>=0)X=pgLeft+o3_relx+LM;else X=pgLeft+o3_relx+iWd-pWd-SB;
}else{X=o3_fixx+LM;}}}
}else{
if(o3_hauto){
if(o3_hpos==LEFT&&OLx-pgLeft<iWd/2&&OLx-pWd-o3_offsetx<pgLeft+LM)o3_hpos=RIGHT;else
if(o3_hpos==RIGHT&&OLx-pgLeft>iWd/2&&OLx+pWd+o3_offsetx>pgLeft+iWd-SB)o3_hpos=LEFT;}
X=(o3_hpos==CENTER)?parseInt(OLx-((pWd+CX)/2)+o3_offsetx):
(o3_hpos==LEFT)?OLx-o3_offsetx-pWd:OLx+o3_offsetx;
if(o3_snapx>1){
snp=X % o3_snapx;
if(o3_hpos==LEFT){X=X-(o3_snapx+snp);}else{X=X+(o3_snapx-snp);}}}
if(!o3_nojustx&&X+pWd>pgLeft+iWd-SB)
X=iWd+pgLeft-pWd-SB;if(!o3_nojustx&&X-LM<pgLeft)X=pgLeft+LM;
pgTop=OLie4?o.scrollTop:o3_frame.pageYOffset;
if(!OLkht&&!nsb&&o&&o.clientHeight)iHt=o.clientHeight;
else if(o3_frame.innerHeight)iHt=o3_frame.innerHeight;
if(OLbubblePI&&o3_bubble)pHt=OLbubbleHt;else pHt=OLns4?over.clip.height:over.offsetHeight;
if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){TM=(o3_shadowy<0)?Math.abs(o3_shadowy):0;
if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)BM=CY=5;else
BM=(o3_shadowy>0)?o3_shadowy:0;CY=Math.abs(o3_shadowy);}
if(o3_ref!=""||o3_fixy> -1||o3_rely!=null||o3_midy!=null){
if(o3_ref!=""){Y=OLrefXY[1];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){
if(o3_refp=='LL'||o3_refp=='LR')Y-=5;}else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){
if(o3_shadowy<0&&(o3_refp=='UL'||o3_refp=='UR'))Y-=o3_shadowy;else
if(o3_shadowy>0&&(o3_refp=='LL'||o3_refp=='LR'))Y-=o3_shadowy;}
}else{if(o3_midy!=null){
Y=parseInt(pgTop+((iHt-pHt-CY)/2)+o3_midy);
}else{if(o3_rely!=null){
if(o3_rely>=0)Y=pgTop+o3_rely+TM;else Y=pgTop+o3_rely+iHt-pHt-BM;}else{
Y=o3_fixy+TM;}}}
}else{
if(o3_vauto){
if(o3_vpos==ABOVE&&OLy-pgTop<iHt/2&&OLy-pHt-o3_offsety<pgTop)o3_vpos=BELOW;else
if(o3_vpos==BELOW&&OLy-pgTop>iHt/2&&OLy+pHt+o3_offsety+((OLns4||OLkht)?17:0)>pgTop+iHt-BM)
o3_vpos=ABOVE;}Y=(o3_vpos==VCENTER)?parseInt(OLy-((pHt+CY)/2)+o3_offsety):
(o3_vpos==ABOVE)?OLy-(pHt+o3_offsety+BM):OLy+o3_offsety+TM;
if(o3_snapy>1){
snp=Y % o3_snapy;
if(pHt>0&&o3_vpos==ABOVE){Y=Y-(o3_snapy+snp);}else{Y=Y+(o3_snapy-snp);}}}
if(!o3_nojusty&&Y+pHt+BM>pgTop+iHt)Y=pgTop+iHt-pHt-BM;if(!o3_nojusty&&Y-TM<pgTop)Y=pgTop+TM;
OLrepositionTo(over,X,Y);
if(OLshadowPI)OLrepositionShadow(X,Y);if(OLiframePI)OLrepositionIfs(X,Y);
if(OLns6&&o3_frame.innerHeight){iHt=o3_frame.innerHeight;OLrepositionTo(over,X,Y);}
if(OLscrollPI)OLchkScroll(X-pgLeft,Y-pgTop);
}
// Chooses body or documentElement
function OLfd(f){
var fd=((f)?f:o3_frame).document,fdc=fd.compatMode,fdd=fd.documentElement;
return (!OLop7&&fdc&&fdc!='BackCompat'&&fdd&&fdd.clientWidth)?fd.documentElement:fd.body;
}
// Gets location of REFerence object
function OLgetRefXY(r){
var o=OLgetRef(r),ob=o,rXY=[o3_refx,o3_refy],of;
if(!o)return [null,null];
if(OLns4){if(typeof o.length!='undefined'&&o.length>1){
ob=o[0];rXY[0]+=o[0].x+o[1].pageX;rXY[1]+=o[0].y+o[1].pageY;
}else{if((o.toString().indexOf('Image')!= -1)||(o.toString().indexOf('Anchor')!= -1)){
rXY[0]+=o.x;rXY[1]+=o.y;}else{rXY[0]+=o.pageX;rXY[1]+=o.pageY;}}
}else{rXY[0]+=OLpageLoc(o,'Left');rXY[1]+=OLpageLoc(o,'Top');}
of=OLgetRefOffsets(ob);rXY[0]+=of[0];rXY[1]+=of[1];
return rXY;
}
function OLgetRef(l){var r=OLgetRefById(l);return (r)?r:OLgetRefByName(l);}
// Seeks REFerence by id
function OLgetRefById(l,d){
var r="",j;l=(l||'overDiv');d=(d||o3_frame.document);
if(OLie4&&d.all){return d.all[l];}else if(d.getElementById){return d.getElementById(l);
}else if(d.layers&&d.layers.length>0){if(d.layers[l])return d.layers[l];
for(j=0;j<d.layers.length;j++){r=OLgetRefById(l,d.layers[j].document);if(r)return r;}}
return null;
}
// Seeks REFerence by name (for img and a)
function OLgetRefByName(l,d){
var r=null,j;d=(d||o3_frame.document);
if(typeof d.images[l]!='undefined'&&d.images[l]){return d.images[l];
}else if(typeof d.anchors[l]!='undefined'&&d.anchors[l]){return d.anchors[l];
}else if(d.layers&&d.layers.length>0){
for(j=0;j<d.layers.length;j++){r=OLgetRefByName(l,d.layers[j].document);
if(r&&r.length>0)return r;else if(r)return [r,d.layers[j]];}}
return null;
}
// Gets layer vs REFerence offsets
function OLgetRefOffsets(o){
var c=o3_refc.toUpperCase(),p=o3_refp.toUpperCase(),W=0,H=0,pW=0,pH=0,of=[0,0];
pW=(OLbubblePI&&o3_bubble)?o3_width:OLns4?over.clip.width:over.offsetWidth;
pH=(OLbubblePI&&o3_bubble)?OLbubbleHt:OLns4?over.clip.height:over.offsetHeight;
if((!OLop7)&&o.toString().indexOf('Image')!= -1){W=o.width;H=o.height;
}else if((!OLop7)&&o.toString().indexOf('Anchor')!= -1){c=o3_refc='UL';}else{
W=(OLns4)?o.clip.width:o.offsetWidth;H=(OLns4)?o.clip.height:o.offsetHeight;}
if((OLns4||(OLns6&&OLgek))&&o.border){W+=2*parseInt(o.border);H+=2*parseInt(o.border);}
if(c=='UL'){of=(p=='UR')?[-pW,0]:(p=='LL')?[0,-pH]:(p=='LR')?[-pW,-pH]:[0,0];
}else if(c=='UR'){of=(p=='UR')?[W-pW,0]:(p=='LL')?[W,-pH]:(p=='LR')?[W-pW,-pH]:[W,0];
}else if(c=='LL'){of=(p=='UR')?[-pW,H]:(p=='LL')?[0,H-pH]:(p=='LR')?[-pW,H-pH]:[0,H];
}else if(c=='LR'){of=(p=='UR')?[W-pW,H]:(p=='LL')?[W,H-pH]:(p=='LR')?[W-pW,H-pH]:
[W,H];}
return of;
}
// Gets x or y location of object
function OLpageLoc(o,t){
var l=0;while(o.offsetParent&&o.offsetParent.tagName.toLowerCase()!='html'){
l+=o['offset'+t];o=o.offsetParent;}l+=o['offset'+t];
return l;
}
// Moves layer
function OLmouseMove(e){
var e=(e||event);
OLcC=(OLovertwoPI&&over2&&over==over2?cClick2:cClick);
OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);
if((OLallowmove&&over)&&(o3_frame==self||over==OLgetRefById())){
OLplaceLayer();if(OLhidePI)OLhideUtil(0,1,1,0,0,0);}
if(OLhover&&over&&o3_frame==self&&OLcursorOff())if(o3_offdelay<1)OLcC();else
{if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=setTimeout("OLcC()",o3_offdelay);}
}
// Capture mouse and chain other scripts.
function OLmh(){
var fN,f,j,k,s,mh=OLmouseMove,w=(OLns4&&window.onmousemove),re=/function[ ]*(\w*)\(/;
OLdw=document;if(document.onmousemove||w){if(w)OLdw=window;f=OLdw.onmousemove.toString();
fN=f.match(re);if(!fN||fN[1]=='anonymous'||fN[1]=='OLmouseMove'){OLchkMh=0;return;}
if(fN[1])s=fN[1]+'(e)';else{j=f.indexOf('{');k=f.lastIndexOf('}')+1;s=f.substring(j,k);}
s+=';OLmouseMove(e);';mh=new Function('e',s);}
OLdw.onmousemove=mh;if(OLns4)OLdw.captureEvents(Event.MOUSEMOVE);
}
/*
PARSING
*/
function OLparseTokens(pf,ar){
var i,v,md= -1,par=(pf!='ol_'),p=OLpar,q=OLparQuo,t=OLtoggle;OLudf=(par&&!ar.length?1:0);
for(i=0;i< ar.length;i++){if(md<0){if(typeof ar[i]=='number'){OLudf=(par?1:0);i--;}
else{switch(pf){case 'ol_':ol_text=ar[i];break;default:o3_text=ar[i];}}md=0;
}else{
if(ar[i]==INARRAY){OLudf=0;eval(pf+'text=ol_texts['+ar[++i]+']');continue;}
if(ar[i]==CAPARRAY){eval(pf+'cap=ol_caps['+ar[++i]+']');continue;}
if(ar[i]==CAPTION){q(ar[++i],pf+'cap');continue;}
if(Math.abs(ar[i])==STICKY){t(ar[i],pf+'sticky');continue;}
if(Math.abs(ar[i])==NOFOLLOW){t(ar[i],pf+'nofollow');continue;}
if(ar[i]==BACKGROUND){q(ar[++i],pf+'background');continue;}
if(Math.abs(ar[i])==NOCLOSE){t(ar[i],pf+'noclose');continue;}
if(Math.abs(ar[i])==MOUSEOFF){t(ar[i],pf+'mouseoff');continue;}
if(ar[i]==OFFDELAY){p(ar[++i],pf+'offdelay');continue;}
if(ar[i]==RIGHT||ar[i]==LEFT||ar[i]==CENTER){p(ar[i],pf+'hpos');continue;}
if(ar[i]==OFFSETX){p(ar[++i],pf+'offsetx');continue;}
if(ar[i]==OFFSETY){p(ar[++i],pf+'offsety');continue;}
if(ar[i]==FGCOLOR){q(ar[++i],pf+'fgcolor');continue;}
if(ar[i]==BGCOLOR){q(ar[++i],pf+'bgcolor');continue;}
if(ar[i]==CGCOLOR){q(ar[++i],pf+'cgcolor');continue;}
if(ar[i]==TEXTCOLOR){q(ar[++i],pf+'textcolor');continue;}
if(ar[i]==CAPCOLOR){q(ar[++i],pf+'capcolor');continue;}
if(ar[i]==CLOSECOLOR){q(ar[++i],pf+'closecolor');continue;}
if(ar[i]==WIDTH){p(ar[++i],pf+'width');continue;}
if(Math.abs(ar[i])==WRAP){t(ar[i],pf+'wrap');continue;}
if(ar[i]==WRAPMAX){p(ar[++i],pf+'wrapmax');continue;}
if(ar[i]==HEIGHT){p(ar[++i],pf+'height');continue;}
if(ar[i]==BORDER){p(ar[++i],pf+'border');continue;}
if(ar[i]==BASE){p(ar[++i],pf+'base');continue;}
if(ar[i]==STATUS){q(ar[++i],pf+'status');continue;}
if(Math.abs(ar[i])==AUTOSTATUS){v=pf+'autostatus';
eval(v+'=('+ar[i]+'<0)?('+v+'==2?2:0):('+v+'==1?0:1)');continue;}
if(Math.abs(ar[i])==AUTOSTATUSCAP){v=pf+'autostatus';
eval(v+'=('+ar[i]+'<0)?('+v+'==1?1:0):('+v+'==2?0:2)');continue;}
if(ar[i]==CLOSETEXT){q(ar[++i],pf+'close');continue;}
if(ar[i]==SNAPX){p(ar[++i],pf+'snapx');continue;}
if(ar[i]==SNAPY){p(ar[++i],pf+'snapy');continue;}
if(ar[i]==FIXX){p(ar[++i],pf+'fixx');continue;}
if(ar[i]==FIXY){p(ar[++i],pf+'fixy');continue;}
if(ar[i]==RELX){p(ar[++i],pf+'relx');continue;}
if(ar[i]==RELY){p(ar[++i],pf+'rely');continue;}
if(ar[i]==MIDX){p(ar[++i],pf+'midx');continue;}
if(ar[i]==MIDY){p(ar[++i],pf+'midy');continue;}
if(ar[i]==REF){q(ar[++i],pf+'ref');continue;}
if(ar[i]==REFC){q(ar[++i],pf+'refc');continue;}
if(ar[i]==REFP){q(ar[++i],pf+'refp');continue;}
if(ar[i]==REFX){p(ar[++i],pf+'refx');continue;}
if(ar[i]==REFY){p(ar[++i],pf+'refy');continue;}
if(ar[i]==FGBACKGROUND){q(ar[++i],pf+'fgbackground');continue;}
if(ar[i]==BGBACKGROUND){q(ar[++i],pf+'bgbackground');continue;}
if(ar[i]==CGBACKGROUND){q(ar[++i],pf+'cgbackground');continue;}
if(ar[i]==PADX){p(ar[++i],pf+'padxl');p(ar[++i],pf+'padxr');continue;}
if(ar[i]==PADY){p(ar[++i],pf+'padyt');p(ar[++i],pf+'padyb');continue;}
if(Math.abs(ar[i])==FULLHTML){t(ar[i],pf+'fullhtml');continue;}
if(ar[i]==BELOW||ar[i]==ABOVE||ar[i]==VCENTER){p(ar[i],pf+'vpos');continue;}
if(ar[i]==CAPICON){q(ar[++i],pf+'capicon');continue;}
if(ar[i]==TEXTFONT){q(ar[++i],pf+'textfont');continue;}
if(ar[i]==CAPTIONFONT){q(ar[++i],pf+'captionfont');continue;}
if(ar[i]==CLOSEFONT){q(ar[++i],pf+'closefont');continue;}
if(ar[i]==TEXTSIZE){q(ar[++i],pf+'textsize');continue;}
if(ar[i]==CAPTIONSIZE){q(ar[++i],pf+'captionsize');continue;}
if(ar[i]==CLOSESIZE){q(ar[++i],pf+'closesize');continue;}
if(ar[i]==TIMEOUT){p(ar[++i],pf+'timeout');continue;}
if(ar[i]==DELAY){p(ar[++i],pf+'delay');continue;}
if(Math.abs(ar[i])==HAUTO){t(ar[i],pf+'hauto');continue;}
if(Math.abs(ar[i])==VAUTO){t(ar[i],pf+'vauto');continue;}
if(Math.abs(ar[i])==NOJUSTX){t(ar[i],pf+'nojustx');continue;}
if(Math.abs(ar[i])==NOJUSTY){t(ar[i],pf+'nojusty');continue;}
if(Math.abs(ar[i])==CLOSECLICK){t(ar[i],pf+'closeclick');continue;}
if(ar[i]==CLOSETITLE){q(ar[++i],pf+'closetitle');continue;}
if(ar[i]==FGCLASS){q(ar[++i],pf+'fgclass');continue;}
if(ar[i]==BGCLASS){q(ar[++i],pf+'bgclass');continue;}
if(ar[i]==CGCLASS){q(ar[++i],pf+'cgclass');continue;}
if(ar[i]==TEXTPADDING){p(ar[++i],pf+'textpadding');continue;}
if(ar[i]==TEXTFONTCLASS){q(ar[++i],pf+'textfontclass');continue;}
if(ar[i]==CAPTIONPADDING){p(ar[++i],pf+'captionpadding');continue;}
if(ar[i]==CAPTIONFONTCLASS){q(ar[++i],pf+'captionfontclass');continue;}
if(ar[i]==CLOSEFONTCLASS){q(ar[++i],pf+'closefontclass');continue;}
if(Math.abs(ar[i])==CAPBELOW){t(ar[i],pf+'capbelow');continue;}
if(ar[i]==LABEL){q(ar[++i],pf+'label');continue;}
if(Math.abs(ar[i])==DECODE){t(ar[i],pf+'decode');continue;}
if(ar[i]==DONOTHING){continue;}
i=OLparseCmdLine(pf,i,ar);}}
if((OLfunctionPI)&&OLudf&&o3_function)o3_text=o3_function();
if(pf=='o3_')OLfontSize();
}
function OLpar(a,v){eval(v+'='+a);}
function OLparQuo(a,v){eval(v+"='"+OLescSglQt(a)+"'");}
function OLescSglQt(s){return s.toString().replace(/'/g,"\\'");}
function OLtoggle(a,v){eval(v+'=('+v+'==0&&'+a+'>=0)?1:0');}
function OLhasDims(s){return /[%\-a-z]+$/.test(s);}
function OLfontSize(){
var i;if(OLhasDims(o3_textsize)){if(OLns4)o3_textsize="2";}else
if(!OLns4){i=parseInt(o3_textsize);o3_textsize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
if(OLhasDims(o3_captionsize)){if(OLns4)o3_captionsize="2";}else
if(!OLns4){i=parseInt(o3_captionsize);o3_captionsize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
if(OLhasDims(o3_closesize)){if(OLns4)o3_closesize="2";}else
if(!OLns4){i=parseInt(o3_closesize);o3_closesize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
if(OLprintPI)OLprintDims();
}
function OLdecode(){
var re=/%[0-9A-Fa-f]{2,}/,t=o3_text,c=o3_cap,u=unescape,d=!OLns4&&(!OLgek||OLgek>=20020826)
&&typeof decodeURIComponent?decodeURIComponent:u;if(typeof(window.TypeError)=='function'){
if(re.test(t)){eval(new Array('try{','o3_text=d(t);','}catch(e){','o3_text=u(t);',
'}').join('\n'))};if(c&&re.test(c)){eval(new Array('try{','o3_cap=d(c);','}catch(e){',
'o3_cap=u(c);','}').join('\n'))}}else{if(re.test(t))o3_text=u(t);if(c&&re.test(c))o3_cap=u(c);}
}
/*
LAYER FUNCTIONS
*/
// Writes to layer
function OLlayerWrite(t){
t+="\n";
if(OLns4){over.document.write(t);over.document.close();
}else if(typeof over.innerHTML!='undefined'){if(OLieM)over.innerHTML='';over.innerHTML=t;
}else{range=o3_frame.document.createRange();range.setStartAfter(over);
domfrag=range.createContextualFragment(t);
while(over.hasChildNodes()){over.removeChild(over.lastChild);}
over.appendChild(domfrag);}
if(OLprintPI)over.print=o3_print?t:null;
}
// Makes object visible
function OLshowObject(o){
OLshowid=0;o=(OLns4)?o:o.style;
if(((OLfilterPI)&&!OLchkFilter(o))||!OLfilterPI)o.visibility="visible";
if(OLshadowPI)OLshowShadow();if(OLiframePI)OLshowIfs();if(OLhidePI)OLhideUtil(1,1,0);
}
// Hides object
function OLhideObject(o){
if(OLshowid>0){clearTimeout(OLshowid);OLshowid=0;}
if(OLtimerid>0)clearTimeout(OLtimerid);if(OLdelayid>0)clearTimeout(OLdelayid);
OLtimerid=0;OLdelayid=0;self.status="";o3_label=ol_label;
if(o3_frame!=self)o=OLgetRefById();
if(o){if(o.onmouseover)o.onmouseover=null;
if(OLscrollPI&&o==over)OLclearScroll();
if(OLdraggablePI)OLclearDrag();
if(OLfilterPI)OLcleanupFilter(o);if(OLshadowPI)OLhideShadow();
var os=(OLns4)?o:o.style;os.visibility="hidden";
if(OLhidePI&&o==over)OLhideUtil(0,0,1);if(OLiframePI)OLhideIfs(o);}
}
// Moves layer
function OLrepositionTo(o,xL,yL){
o=(OLns4)?o:o.style;
if(o.setAttribute) {
o.setAttribute('left', OLns4?xL:xL+'px');
o.setAttribute('top', OLns4?yL:yL+'px');
} else {
o.left=(OLns4?xL:xL+'px');
o.top=(OLns4?yL:yL+'px');
}
}
// Handle NOCLOSE-MOUSEOFF
function OLoptMOUSEOFF(c){
if(!c)o3_close="";
over.onmouseover=function(){OLhover=1;if(OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}}
}
function OLcursorOff(){
var o=(OLns4?over:over.style),pHt=OLns4?over.clip.height:over.offsetHeight,
left=parseInt(o.left),top=parseInt(o.top),
right=left+o3_width,bottom=top+((OLbubblePI&&o3_bubble)?OLbubbleHt:pHt);
if(OLx<left||OLx>right||OLy<top||OLy>bottom)return true;
return false;
}
/*
REGISTRATION
*/
function OLsetRunTimeVar(){
if(OLrunTime.length)for(var k=0;k<OLrunTime.length;k++)OLrunTime[k]();
}
function OLparseCmdLine(pf,i,ar){
if(OLcmdLine.length){for(var k=0;k<OLcmdLine.length;k++){
var j=OLcmdLine[k](pf,i,ar);if(j>-1){i=j;break;}}}
return i;
}
function OLregCmds(c){
if(typeof c!='string')return;
var pM=c.split(',');pMtr=pMtr.concat(pM);
for(var i=0;i<pM.length;i++)eval(pM[i].toUpperCase()+'='+pmCnt++);
}
function OLregRunTimeFunc(f){
if(typeof f=='object')OLrunTime=OLrunTime.concat(f);
else OLrunTime[OLrunTime.length++]=f;
}
function OLregCmdLineFunc(f){
if(typeof f=='object')OLcmdLine=OLcmdLine.concat(f);
else OLcmdLine[OLcmdLine.length++]=f;
}
OLloaded=1;

View File

@@ -0,0 +1,169 @@
/*
Artistic License 2.0
Copyright (c) 2000-2006, The Perl Foundation.
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software.
You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement.
Definitions
"Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package.
"Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures.
"You" and "your" means any person who would like to copy, distribute, or modify the Package.
"Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version.
"Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization.
"Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees.
"Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder.
"Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder.
"Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future.
"Source" form means the source code, documentation source, and configuration files for the Package.
"Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form.
Permission for Use and Modification Without Distribution
(1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version.
Permissions for Redistribution of the Standard Version
(2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package.
(3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License.
Distribution of Modified Versions of the Package as Source
(4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following:
(a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version.
(b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version.
(c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under
(i) the Original License or
(ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed.
Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source
(5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license.
(6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version.
Aggregating or Linking the Package
(7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation.
(8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package.
Items That are Not Considered Part of a Modified Version
(9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license.
General Provisions
(10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.
(11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.
(12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.
(13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.
(14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
overlibmws_iframe.js plug-in module - Copyright Foteos Macrides 2003-2005
Masks system controls to prevent obscuring of popops for IE v5.5 or higher.
Initial: October 19, 2003 - Last Revised: May 15, 2005
See the Change History and Command Reference for overlibmws via:
http://www.macridesweb.com/oltest/
Published under an open source license: http://www.macridesweb.com/oltest/license.html
*/
OLloaded=0;
var OLifsP1=null,OLifsSh=null,OLifsP2=null;
// IFRAME SHIM SUPPORT FUNCTIONS
function OLinitIfs(){
if(!OLie55)return;
if((OLovertwoPI)&&over2&&over==over2){
var o=o3_frame.document.all['overIframeOvertwo'];
if(!o||OLifsP2!=o){OLifsP2=null;OLgetIfsP2Ref();}return;}
o=o3_frame.document.all['overIframe'];
if(!o||OLifsP1!=o){OLifsP1=null;OLgetIfsRef();}
if((OLshadowPI)&&o3_shadow){o=o3_frame.document.all['overIframeShadow'];
if(!o||OLifsSh!=o){OLifsSh=null;OLgetIfsShRef();}}
}
function OLsetIfsRef(o,i,z){
o.id=i;o.src='javascript:false;';o.scrolling='no';var os=o.style;
os.position='absolute';os.top=0;os.left=0;os.width=1;os.height=1;os.visibility='hidden';
os.zIndex=over.style.zIndex-z;os.filter='Alpha(style=0,opacity=0)';
}
function OLgetIfsRef(){
if(OLifsP1||!OLie55)return;
OLifsP1=o3_frame.document.createElement('iframe');
OLsetIfsRef(OLifsP1,'overIframe',2);
o3_frame.document.body.appendChild(OLifsP1);
}
function OLgetIfsShRef(){
if(OLifsSh||!OLie55)return;
OLifsSh=o3_frame.document.createElement('iframe');
OLsetIfsRef(OLifsSh,'overIframeShadow',3);
o3_frame.document.body.appendChild(OLifsSh);
}
function OLgetIfsP2Ref(){
if(OLifsP2||!OLie55)return;
OLifsP2=o3_frame.document.createElement('iframe');
OLsetIfsRef(OLifsP2,'overIframeOvertwo',1);
o3_frame.document.body.appendChild(OLifsP2);
}
function OLsetDispIfs(o,w,h){
var os=o.style;
os.width=w+'px';os.height=h+'px';os.clip='rect(0px '+w+'px '+h+'px 0px)';
o.filters.alpha.enabled=true;
}
function OLdispIfs(){
if(!OLie55)return;
var wd=over.offsetWidth,ht=over.offsetHeight;
if(OLfilterPI&&o3_filter&&o3_filtershadow){wd+=5;ht+=5;}
if((OLovertwoPI)&&over2&&over==over2){
if(!OLifsP2)return;
OLsetDispIfs(OLifsP2,wd,ht);return;}
if(!OLifsP1)return;
OLsetDispIfs(OLifsP1,wd,ht);
if((!OLshadowPI)||!o3_shadow||!OLifsSh)return;
OLsetDispIfs(OLifsSh,wd,ht);
}
function OLshowIfs(){
if(OLifsP1){OLifsP1.style.visibility="visible";
if((OLshadowPI)&&o3_shadow&&OLifsSh)OLifsSh.style.visibility="visible";}
}
function OLhideIfs(o){
if(!OLie55||o!=over)return;
if(OLifsP1)OLifsP1.style.visibility="hidden";
if((OLshadowPI)&&o3_shadow&&OLifsSh)OLifsSh.style.visibility="hidden";
}
function OLrepositionIfs(X,Y){
if(OLie55){if((OLovertwoPI)&&over2&&over==over2){
if(OLifsP2)OLrepositionTo(OLifsP2,X,Y);}
else{if(OLifsP1){OLrepositionTo(OLifsP1,X,Y);if((OLshadowPI)&&o3_shadow&&OLifsSh)
OLrepositionTo(OLifsSh,X+o3_shadowx,Y+o3_shadowy);}}}
}
OLiframePI=1;
OLloaded=1;

View File

@@ -0,0 +1,237 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
function send_back(module, id)
{
var associated_row_data = associated_javascript_data[id];
// cn: bug 12274 - stripping false-positive security envelope
eval("var temp_request_data = " + window.document.forms['popup_query_form'].request_data.value);
if(temp_request_data.jsonObject) {
var request_data = temp_request_data.jsonObject;
} else {
var request_data = temp_request_data; // passed data that is NOT incorrectly encoded via JSON.encode();
}
// cn: end bug 12274 fix
var passthru_data = Object();
if(typeof(request_data.passthru_data) != 'undefined')
{
passthru_data = request_data.passthru_data;
}
var form_name = request_data.form_name;
var field_to_name_array = request_data.field_to_name_array;
var call_back_function = eval("window.opener." + request_data.call_back_function);
var array_contents = Array();
// constructs the array of values associated to the bean that the user clicked
for(var the_key in field_to_name_array)
{
if(the_key != 'toJSON')
{
var the_name = field_to_name_array[the_key];
var the_value = '';
if(module != '' && id != '')
{
if((the_key.toUpperCase() == 'USER_NAME' || the_key.toUpperCase() == 'LAST_NAME' || the_key.toUpperCase() == 'FIRST_NAME') && typeof(is_show_fullname) != 'undefined' && is_show_fullname && form_name != 'search_form') {//if it is from searchform, it will search by assigned_user_name like 'ABC%', then it will return nothing
the_value = associated_row_data['FULL_NAME'];
}
else {
the_value = associated_row_data[the_key.toUpperCase()];
}
}
if (typeof(the_value) == 'string') {
the_value = the_value.replace(/\r\n/g, '\\n');
}
array_contents.push('"' + the_name + '":"' + the_value + '"');
}
}
eval("var name_to_value_array = {" + array_contents.join(",") + "}");
var result_data = {"form_name":form_name,"name_to_value_array":name_to_value_array,"passthru_data":passthru_data};
var close_popup = window.opener.get_close_popup();
call_back_function(result_data);
if(close_popup)
{
window.close();
}
}
function send_back_teams(module, form, field, error_message, request_data, form_team_id) {
var array_contents = Array();
if(form_team_id){
array_contents.push(form_team_id);
}else{
var j=0;
for (i = 0; i < form.elements.length; i++){
if(form.elements[i].name == field) {
if (form.elements[i].checked == true) {
array_contents.push(form.elements[i].value);
}
}
}
}
if (array_contents.length ==0 ) {
window.alert(error_message);
return;
}
var field_to_name_array = request_data.field_to_name_array;
var array_teams = new Array();
for(team_id in array_contents) {
if(typeof array_contents[team_id] == 'string') {
var team = {"team_id" : associated_javascript_data[array_contents[team_id]].ID,
"team_name" : associated_javascript_data[array_contents[team_id]].NAME};
array_teams.push(team);
}
}
var passthru_data = Object();
if(typeof request_data.call_back_function == 'undefined' && typeof request_data == 'object') {
request_data = YAHOO.lang.JSON.parse(request_data.value);
}
if(typeof(request_data.passthru_data) != 'undefined')
{
passthru_data = request_data.passthru_data;
}
var form_name = request_data.form_name;
var field_name = request_data.field_name;
var call_back_function = eval("window.opener." + request_data.call_back_function);
var result_data={"form_name":form_name,"field_name":field_name,"teams":array_teams,"passthru_data":passthru_data};
var close_popup = window.opener.get_close_popup();
call_back_function(result_data);
if(close_popup)
{
window.close();
}
}
function send_back_selected(module, form, field, error_message, request_data)
{
var array_contents = Array();
var j=0;
for (i = 0; i < form.elements.length; i++){
if(form.elements[i].name == field) {
if (form.elements[i].checked == true) {
++j;
array_contents.push('"' + "ID_" + j + '":"' + form.elements[i].value + '"');
}
}
}
if (array_contents.length ==0 ) {
window.alert(error_message);
return;
}
eval("var selection_list_array = {" + array_contents.join(",") + "}");
// cn: bug 12274 - stripping false-positive security envelope
eval("var temp_request_data = " + window.document.forms['popup_query_form'].request_data.value);
if(temp_request_data.jsonObject) {
var request_data = temp_request_data.jsonObject;
} else {
var request_data = temp_request_data; // passed data that is NOT incorrectly encoded via JSON.encode();
}
// cn: end bug 12274 fix
var passthru_data = Object();
if(typeof(request_data.passthru_data) != 'undefined')
{
passthru_data = request_data.passthru_data;
}
var form_name = request_data.form_name;
var field_to_name_array = request_data.field_to_name_array;
var call_back_function = eval("window.opener." + request_data.call_back_function);
var result_data={"form_name":form_name,"selection_list":selection_list_array ,"passthru_data":passthru_data};
var close_popup = window.opener.get_close_popup();
call_back_function(result_data);
if(close_popup)
{
window.close();
}
}
function toggleMore(spanId, img_id, module, action, params){
toggle_more_go = function() {
oReturn = function(body, caption, width, theme) {
return overlib(body, CAPTION, caption, STICKY, MOUSEOFF, 1000, WIDTH, width, CLOSETEXT, ('<img border=0 style="margin-left:2px; margin-right: 2px;" src=themes/' + theme + '/images/close.gif>'), CLOSETITLE, 'Click to Close', CLOSECLICK, FGCLASS, 'olFgClass', CGCLASS, 'olCgClass', BGCLASS, 'olBgClass', TEXTFONTCLASS, 'olFontClass', CAPTIONFONTCLASS, 'olCapFontClass', CLOSEFONTCLASS, 'olCloseFontClass', REF, spanId, REFC, 'LL', REFX, 13);
}
success = function(data) {
eval(data.responseText);
SUGAR.util.additionalDetailsCache[spanId] = new Array();
SUGAR.util.additionalDetailsCache[spanId]['body'] = result['body'];
SUGAR.util.additionalDetailsCache[spanId]['caption'] = result['caption'];
SUGAR.util.additionalDetailsCache[spanId]['width'] = result['width'];
SUGAR.util.additionalDetailsCache[spanId]['theme'] = result['theme'];
ajaxStatus.hideStatus();
return oReturn(SUGAR.util.additionalDetailsCache[spanId]['body'], SUGAR.util.additionalDetailsCache[spanId]['caption'], SUGAR.util.additionalDetailsCache[spanId]['width'], SUGAR.util.additionalDetailsCache[spanId]['theme']);
}
if(typeof SUGAR.util.additionalDetailsCache[spanId] != 'undefined')
return oReturn(SUGAR.util.additionalDetailsCache[spanId]['body'], SUGAR.util.additionalDetailsCache[spanId]['caption'], SUGAR.util.additionalDetailsCache[spanId]['width'], SUGAR.util.additionalDetailsCache[spanId]['theme']);
if(typeof SUGAR.util.additionalDetailsCalls[spanId] != 'undefined') // call already in progress
return;
ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_LOADING'));
url = 'index.php?module='+module+'&action='+action+'&'+params;
SUGAR.util.additionalDetailsCalls[spanId] = YAHOO.util.Connect.asyncRequest('GET', url, {success: success, failure: success});
return false;
}
SUGAR.util.additionalDetailsRpcCall = window.setTimeout('toggle_more_go()', 250);
}

View File

@@ -0,0 +1,209 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
var popup_request_data;
var close_popup;
function get_popup_request_data()
{
return window.document.popup_request_data;
}
function get_close_popup()
{
return window.document.close_popup;
}
function open_popup(module_name, width, height, initial_filter, close_popup, hide_clear_button, popup_request_data, popup_mode, create, metadata)
{
if (typeof(popupCount) == "undefined" || popupCount == 0)
popupCount = 1;
// set the variables that the popup will pull from
window.document.popup_request_data = popup_request_data;
window.document.close_popup = close_popup;
// launch the popup
URL = 'index.php?'
+ 'module=' + module_name
+ '&action=Popup';
if(initial_filter != '')
{
URL += '&query=true' + initial_filter;
}
if(hide_clear_button)
{
URL += '&hide_clear_button=true';
}
windowName = module_name + '_popup_window' + popupCount;
popupCount++;
windowFeatures = 'width=' + width
+ ',height=' + height
+ ',resizable=1,scrollbars=1';
if (popup_mode == '' && popup_mode == 'undefined') {
popup_mode='single';
}
URL+='&mode='+popup_mode;
if (create == '' && create == 'undefined') {
create = 'false';
}
URL+='&create='+create;
if (metadata != '' && metadata != 'undefined') {
URL+='&metadata='+metadata;
}
win = window.open(URL, windowName, windowFeatures);
if(window.focus)
{
// put the focus on the popup if the browser supports the focus() method
win.focus();
}
win.popupCount = popupCount;
return win;
}
/**
* The reply data must be a JSON array structured with the following information:
* 1) form name to populate
* 2) associative array of input names to values for populating the form
*/
var from_popup_return = false;
function set_return(popup_reply_data)
{
from_popup_return = true;
var form_name = popup_reply_data.form_name;
var name_to_value_array = popup_reply_data.name_to_value_array;
for (var the_key in name_to_value_array)
{
if(the_key == 'toJSON')
{
/* just ignore */
}
else
{
var displayValue=name_to_value_array[the_key].replace(/&amp;/gi,'&').replace(/&lt;/gi,'<').replace(/&gt;/gi,'>').replace(/&#039;/gi,'\'').replace(/&quot;/gi,'"');;
if(window.document.forms[form_name] && window.document.forms[form_name].elements[the_key])
window.document.forms[form_name].elements[the_key].value = displayValue;
}
}
}
function set_return_and_save(popup_reply_data)
{
var form_name = popup_reply_data.form_name;
var name_to_value_array = popup_reply_data.name_to_value_array;
for (var the_key in name_to_value_array)
{
if(the_key == 'toJSON')
{
/* just ignore */
}
else
{
window.document.forms[form_name].elements[the_key].value = name_to_value_array[the_key];
}
}
window.document.forms[form_name].return_module.value = window.document.forms[form_name].module.value;
window.document.forms[form_name].return_action.value = 'DetailView';
window.document.forms[form_name].return_id.value = window.document.forms[form_name].record.value;
window.document.forms[form_name].action.value = 'Save';
window.document.forms[form_name].submit();
}
function set_return_and_save_targetlist(popup_reply_data)
{
var form_name = popup_reply_data.form_name;
var name_to_value_array = popup_reply_data.name_to_value_array;
var form_index = document.forms.length - 1;
sugarListView.get_checks();
var uids = document.MassUpdate.uid.value;
if (uids == '') {
return false;
}
/*
* Add the value returned from the popup to the form for submittal
*/
for (var the_key in name_to_value_array)
{
if(the_key == 'toJSON')
{
/* just ignore */
}
else
{
for ( i = form_index; i >= 0; i--)
{
if ( form_name == window.document.forms[form_index] )
{
form_index = i;
break;
}
}
window.document.forms[form_index].elements[the_key].value = name_to_value_array[the_key];
}
}
window.document.forms[form_index].return_module.value = window.document.forms[form_index].module.value;
window.document.forms[form_index].return_action.value = 'ListView';
window.document.forms[form_index].uids.value = uids;
window.document.forms[form_index].submit();
}
/**
* This is a helper function to construct the initial filter that can be
* passed into the open_popup() function. It assumes that there is an
* account_id and account_name field in the given form_name to use to
* construct the intial filter string.
*/
function get_initial_filter_by_account(form_name)
{
var account_id = window.document.forms[form_name].account_id.value;
var account_name = escape(window.document.forms[form_name].account_name.value);
var initial_filter = "&account_id=" + account_id + "&account_name=" + account_name;
return initial_filter;
}

View File

@@ -0,0 +1,290 @@
JSON = YAHOO.lang.JSON;
SUGAR.quickCompose= {};
SUGAR.quickCompose = function() {
return {
parentPanel : null,
dceMenuPanel : null,
options: null,
loadingMessgPanl : null,
frameLoaded : false,
resourcesLoaded: false,
tinyLoaded : false,
/**
* Get the required compose package in an ajax call required for
* the quick compose.
* @method initComposePackage
* @param {Array} c Options containing compose package and full return url.
* @return {} none
**/
initComposePackage: function(c)
{
//Init fix for YUI 2.7.0 datatable sort.
SUGAR.email2.addressBook.initFixForDatatableSort();
//JS resources must have been loaded if we reach this step.
SUGAR.quickCompose.resourcesLoaded = true;
var callback =
{
success: function(o)
{
var responseData = YAHOO.lang.JSON.parse(o.responseText);
//Create and insert the necessary script tag
var scriptTag = document.createElement('script');
scriptTag.id = 'quickComposeScript';
scriptTag.setAttribute('type','text/javascript');
if(YAHOO.env.ua.ie > 0) //IE hack
scriptTag.text = responseData.jsData;
else //Everybody else
scriptTag.appendChild(document.createTextNode(responseData.jsData));
document.getElementsByTagName("head")[0].appendChild(scriptTag);
//Create and insert the necessary div elements and html markup
var divTag = document.createElement("div");
divTag.innerHTML = responseData.divData;
divTag.id = 'quickCompose';
YAHOO.util.Dom.insertBefore(divTag, 'footer');
//Set the flag that we loaded the compose package.
SUGAR.quickCompose.frameLoaded = true;
//Init the UI
SUGAR.quickCompose.initUI(c.data);
}
}
if(!SUGAR.quickCompose.frameLoaded)
YAHOO.util.Connect.asyncRequest('GET', 'index.php?entryPoint=GenerateQuickComposeFrame', callback, null);
else
SUGAR.quickCompose.initUI(c.data);
},
/**
* Initalize the UI for the quick compose
* the quick compose.
* @method initComposePackage
* @param {Array} options Options containing compose package and full return url.
* @return {} none
**/
initUI: function(options)
{
var SQ = SUGAR.quickCompose;
this.options = options;
//Hide the loading div
loadingMessgPanl.hide();
dce_mode = (typeof this.dceMenuPanel != 'undefined' && this.dceMenuPanel != null) ? true : false;
//Destroy the previous quick compose panel to get a clean slate
if (SQ.parentPanel != null)
{
//First clean up the tinyMCE instance
tinyMCE.execCommand('mceRemoveControl', false, SUGAR.email2.tinyInstances.currentHtmleditor);
SUGAR.email2.tinyInstances[SUGAR.email2.tinyInstances.currentHtmleditor] = null;
SUGAR.email2.tinyInstances.currentHtmleditor = "";
SQ.parentPanel.destroy();
SQ.parentPanel = null;
}
theme = SUGAR.themes.theme_name;
//The quick compose utalizes the EmailUI compose functionality which allows for multiple compose
//tabs. Quick compose always has only one compose screen with an index of 0.
var idx = 0;
//Get template engine with template
if (!SE.composeLayout.composeTemplate)
SE.composeLayout.composeTemplate = new YAHOO.SUGAR.Template(SE.templates['compose']);
panel_modal = dce_mode ? false : true;
panel_width = '880px';
panel_constrain = dce_mode ? false : true;
panel_height = dce_mode ? '450px' : '400px';
panel_shadow = dce_mode ? false : true;
panel_draggable = dce_mode ? false : true;
panel_resize = dce_mode ? false : true;
panel_close = dce_mode ? false : true;
SQ.parentPanel = new YAHOO.widget.Panel("container1", {
modal: panel_modal,
visible: true,
constraintoviewport: panel_constrain,
width : panel_width,
height : panel_height,
shadow : panel_shadow,
draggable : panel_draggable,
resize: panel_resize,
close: panel_close
});
if(!dce_mode) {
SQ.parentPanel.setHeader( SUGAR.language.get('app_strings','LBL_EMAIL_QUICK_COMPOSE')) ;
}
SQ.parentPanel.setBody("<div class='email'><div id='htmleditordiv" + idx + "'></div></div>");
var composePanel = SE.composeLayout.getQuickComposeLayout(SQ.parentPanel,this.options);
if(!dce_mode) {
var resize = new YAHOO.util.Resize('container1', {
handles: ['br'],
autoRatio: false,
minWidth: 400,
minHeight: 350,
status: false
});
resize.on('resize', function(args) {
var panelHeight = args.height;
this.cfg.setProperty("height", panelHeight + "px");
var layout = SE.composeLayout[SE.composeLayout.currentInstanceId];
layout.set("height", panelHeight - 50);
layout.resize(true);
SE.composeLayout.resizeEditor(SE.composeLayout.currentInstanceId);
}, SQ.parentPanel, true);
}
YAHOO.util.Dom.setStyle("container1", "z-index", 1);
if (!SQ.tinyLoaded)
{
//TinyMCE bug, since we are loading the js file dynamically we need to let tiny know that the
//dom event has fired.
tinymce.dom.Event.domLoaded = true;
tinyMCE.init({
convert_urls : false,
theme_advanced_toolbar_align : tinyConfig.theme_advanced_toolbar_align,
width: tinyConfig.width,
theme: tinyConfig.theme,
theme_advanced_toolbar_location : tinyConfig.theme_advanced_toolbar_location,
theme_advanced_buttons1 : tinyConfig.theme_advanced_buttons1,
theme_advanced_buttons2 : tinyConfig.theme_advanced_buttons2,
theme_advanced_buttons3 : tinyConfig.theme_advanced_buttons3,
plugins : tinyConfig.plugins,
elements : tinyConfig.elements,
language : tinyConfig.language,
extended_valid_elements : tinyConfig.extended_valid_elements,
mode: tinyConfig.mode,
strict_loading_mode : true
});
SQ.tinyLoaded = true;
}
SQ.parentPanel.show();
//Re-declare the close function to handle appropriattely.
SUGAR.email2.composeLayout.forceCloseCompose = function(o){SUGAR.quickCompose.parentPanel.hide(); }
if(!dce_mode) {
SQ.parentPanel.center();
}
},
/**
* Display a loading pannel and start retrieving the quick compose requirements.
* @method init
* @param {Array} o Options containing compose package and full return url.
* @return {} none
**/
init: function(o) {
if(typeof o.menu_id != 'undefined') {
this.dceMenuPanel = o.menu_id;
} else {
this.dceMenuPanel = null;
}
loadingMessgPanl = new YAHOO.widget.SimpleDialog('loading', {
width: '200px',
close: true,
modal: true,
visible: true,
fixedcenter: true,
constraintoviewport: true,
draggable: false
});
loadingMessgPanl.setHeader(SUGAR.language.get('app_strings','LBL_EMAIL_PERFORMING_TASK'));
loadingMessgPanl.setBody(SUGAR.language.get('app_strings','LBL_EMAIL_ONE_MOMENT'));
loadingMessgPanl.render(document.body);
loadingMessgPanl.show();
//If JS files havn't been loaded, perform the load.
if(! SUGAR.quickCompose.resourcesLoaded )
this.loadResources(o);
else
this.initUI(o);
},
/**
* Pull in all the required js files.
* @method loadResources
* @param {Array} o Options containing compose package and full return url.
* @return {} none
**/
loadResources: function(o)
{
//IE Bug fix for TinyMCE when pulling in the js file dynamically.
window.skipTinyMCEInitPhase = true;
var require = ["layout", "element", "tabview", "menu","cookie","tinymce","securejson","sugarwidgets","sugarquickcompose","sugarquickcomposecss"];
var loader = new YAHOO.util.YUILoader({
require : require,
loadOptional: true,
skin: { base: 'blank', defaultSkin: '' },
data: o,
onSuccess: this.initComposePackage,
allowRollup: true,
base: "include/javascript/yui/build/"
});
//TiinyMCE cannot be added into the sugar_grp_quickcomp file as it breaks the build, needs to be loaded
//seperately.
loader.addModule({
name :"tinymce",
type : "js",
varName: "TinyMCE",
fullpath: "include/javascript/tiny_mce/tiny_mce.js"
});
loader.addModule({
name :"securejson",
type : "js",
varName: "JSON",
fullpath: "include/JSON.js"
});
//Load the Sugar widgets with dependancies on the yui library.
loader.addModule({
name :"sugarwidgets",
type : "js",
fullpath: "include/javascript/sugarwidgets/SugarYUIWidgets.js",
varName: "YAHOO.SUGAR",
requires: ["datatable", "dragdrop", "treeview", "tabview"]
});
//Load the main components for the quick create compose screen.
loader.addModule({
name :"sugarquickcompose",
type : "js",
varName: "SUGAR.email2.complexLayout",
requires: ["layout", "sugarwidgets", "tinymce"],
fullpath: "include/javascript/sugar_grp_quickcomp.js"
});
//Load the css needed for the quickCompose.
loader.addModule({
name :"sugarquickcomposecss",
type : "css",
fullpath: "modules/Emails/EmailUI.css"
});
loader.insert();
}
};
}();

View File

@@ -0,0 +1,248 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
/**
* browse document for quickSearch fields
* Compatible ExtJS 1.1.1 and ExtJS 2.0
* parameter : noReload - if set to true, enableQS will enable only
* the new sqsEnabled field on the page. If set to false
* it will reload all the sqsEnabled fields.
*/
function enableQS(noReload){
YAHOO.util.Event.onDOMReady(function(){
//Safety check. If sqs_objects variable is null, we really can't do anything useful
if(typeof sqs_objects == 'undefined') {
return;
}
var Dom = YAHOO.util.Dom;
//Get all the fields where sqsEnabled is an attribue, these should be the input text fields for quicksearch
var qsFields = Dom.getElementsByClassName('sqsEnabled');
//Now loop through all these fields and process them
for(qsField in qsFields){
//Safety checks to skip processing of invalid entries
if(typeof qsFields[qsField] == 'function' || typeof qsFields[qsField].id == 'undefined') {
continue;
}
//Create the index we are using to search for the sqs_objects Array
form_id = qsFields[qsField].form.getAttribute('id');
//This is a special case where there is an element with id attribute value of "id"
//In this case, we get the real_id attribute (occurs in modules/Import/tpls/step3.tpl only).
if(typeof form_id == 'object' && qsFields[qsField].form.getAttribute('real_id')) {
form_id = qsFields[qsField].form.getAttribute('real_id');
}
qs_index_id = form_id + '_' + qsFields[qsField].name;
//Another safety check, if the sqs_objects entry is not defined, we can't do anything useful
if(typeof sqs_objects[qs_index_id] == 'undefined') {
qs_index_id = qsFields[qsField].name;
if(typeof sqs_objects[qs_index_id] == 'undefined') {
continue;
}
}
//Track if this field has already been processed. The way the enableQS function is called
//is a bit problematic in that it lends itself to a lot of duplicate processing
if(QSProcessedFieldsArray[qs_index_id]) {
continue;
}
//Store sqs_objects entry as a reference for convenience
var qs_obj = sqs_objects[qs_index_id];
//The loaded variable will be used to check whether or not the quick search field should be created
var loaded = false;
if (!document.forms[qs_obj.form]) {
continue;
}
//Skip quicksearch fields that are readOnly or that are disabled since you can't search on them anyway
if (!document.forms[qs_obj.form].elements[qsFields[qsField].id].readOnly && qs_obj['disable'] != true) {
combo_id = qs_obj.form + '_' + qsFields[qsField].id;
if (Dom.get(combo_id + "_results")) {
loaded = true
}
// if loaded == false, then we do the heavy lifting to re-create the quicksearch field
if (!loaded) {
QSProcessedFieldsArray[qs_index_id] = true;
qsFields[qsField].form_id = form_id;
var sqs = sqs_objects[qs_index_id];
//Initialize the result div
var resultDiv = document.createElement('div');
resultDiv.id = combo_id + "_results";
Dom.insertAfter(resultDiv, qsFields[qsField]);
//Add the module to the fields so we can read it from the response
var fields = qs_obj.field_list.slice();
fields[fields.length] = "module";
//Create the DataSource for this QS
var ds = new YAHOO.util.DataSource("index.php?", {
responseType: YAHOO.util.XHRDataSource.TYPE_JSON,
responseSchema: {
resultsList: 'fields',
total: 'totalCount',
fields: fields,
metaNode: "fields",
metaFields: {total: 'totalCount', fields:"fields"}
},
connMethodPost: true
});
// Don't force selection for search fields
var forceSelect = !((qsFields[qsField].form && typeof(qsFields[qsField].form) == 'object' && qsFields[qsField].form.name == 'search_form')
|| qsFields[qsField].className.match('sqsNoAutofill') != null);
//Finally Declare the Autocomplete
var search = new YAHOO.widget.AutoComplete(qsFields[qsField], resultDiv, ds, {
typeAhead: forceSelect,
forceSelection : forceSelect,
fields: fields,
sqs : sqs,
animSpeed : 0.25,
qs_obj: qs_obj,
//YUI requires the data, even POST, to be URL encoded
generateRequest : function(sQuery) {
var out = SUGAR.util.paramsToUrl({
to_pdf: 'true',
module: 'Home',
action: 'quicksearchQuery',
data: encodeURIComponent(YAHOO.lang.JSON.stringify(this.sqs)),
query: sQuery
});
return out;
},
//Method to fill in form fields with the returned results.
//Should be called on select, and must be called from the AC instance scope.
setFields : function (data, filter) {
for(var i in this.fields) {
for (var key in this.qs_obj.field_list) {
//Check that the field exists and matches the filter
if (this.fields[i] == this.qs_obj.field_list[key] &&
document.forms[this.qs_obj.form].elements[this.qs_obj.populate_list[key]] &&
this.qs_obj.populate_list[key].match(filter)) {
document.forms[this.qs_obj.form].elements[this.qs_obj.populate_list[key]].value = data[i];
}
}
}
},
clearFields : function() {
for (var key in this.qs_obj.field_list) {
if (document.forms[this.qs_obj.form].elements[this.qs_obj.populate_list[key]]){
document.forms[this.qs_obj.form].elements[this.qs_obj.populate_list[key]].value = "";
}
}
this.oldValue = "";
}
});
//fill in the data fields on selection
search.itemSelectEvent.subscribe(function(e, args){
var data = args[2];
var fields = this.fields;
this.setFields(data, /\S/);
//Handle special case where post_onblur_function is set
if (typeof(this.qs_obj['post_onblur_function']) != 'undefined') {
collection_extended = new Array();
for (var i in fields) {
for (var key in this.qs_obj.field_list) {
if (fields[i] == this.qs_obj.field_list[key]) {
collection_extended[this.qs_obj.field_list[key]] = data[i];
}
}
}
eval(this.qs_obj['post_onblur_function'] + '(collection_extended, this.qs_obj.id)');
}
});
// We will get the old value firstly when the field lose focus.
search.textboxFocusEvent.subscribe(function(){
this.oldValue = this.getInputEl().value;
});
//If there is no change for this qucik search field , the value of it will not be cleared.
search.selectionEnforceEvent.subscribe(function(e, args){
if (this.oldValue != args[1]) {
this.clearFields();
} else {
this.getInputEl().value = this.oldValue;
}
});
search.dataReturnEvent.subscribe(function(e, args){
//Selected the first returned value if a tab was done before results were returned
if (this.getInputEl().value.length == 0 && args[2].length > 0) {
var data = [];
for(var key in this.qs_obj.field_list) {
data[data.length] = args[2][0][this.qs_obj.field_list[key]];
}
this.getInputEl().value = data[this.key];
this.itemSelectEvent.fire(this, "", data);
}
});
if (typeof QSFieldsArray[combo_id] == 'undefined' && qsFields[qsField].id) {
QSFieldsArray[combo_id] = search;
}
}
}
}
});
}
function registerSingleSmartInputListener(input) {
if ((c = input.className) && (c.indexOf("sqsEnabled") != -1)) {
enableQS(true);
}
}
if(typeof QSFieldsArray == 'undefined') {
QSFieldsArray = new Array();
QSProcessedFieldsArray = new Array();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
SUGAR_callsInProgress = 0;
YAHOO.util.Connect.completeEvent.subscribe(function(event, data){
SUGAR_callsInProgress--;
if (SUGAR.util.isLoginPage(data[0].conn.responseText))
return false;
});
YAHOO.util.Connect.startEvent.subscribe(function(event, data)
{
SUGAR_callsInProgress++;
});

View File

@@ -0,0 +1,50 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
/**
* @author dwheeler
*/
//Load up the YUI loader and go!
SUGAR.yui = {
loader : new YAHOO.util.YUILoader()
}
SUGAR.yui.loader.addModule({
name:'sugarwidgets',
type:'js',
path:'SugarYUIWidgets.js',
requires:['yahoo', 'layout', 'dragdrop', 'treeview', 'json', 'datatable', 'container', 'button', 'tabview'],
varname: YAHOO.SUGAR
});

View File

@@ -0,0 +1,676 @@
/*********************************************************************************
* SugarCRM is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
* technical reasons, the Appropriate Legal Notices must display the words
* "Powered by SugarCRM".
********************************************************************************/
YAHOO.namespace("SUGAR");
(function() {
var sw = YAHOO.SUGAR,
Event = YAHOO.util.Event,
Connect = YAHOO.util.Connect,
Dom = YAHOO.util.Dom;
/**
* Message Box is a singleton widget designed to replace the browsers 'alert'
* function, as well as provide capabilities for pop-over loading bars and
* other small non-interactive pop-overs.
* TODO:Still needs configurable buttons in the footer as well as
* auto building of a loading bar.
*/
sw.MessageBox = {
progressTemplate : "{body}<br><div class='sugar-progress-wrap'><div class='sugar-progress-bar'/></div>",
promptTemplate : "{body}:<input id='sugar-message-prompt' class='sugar-message-prompt' name='sugar-message-prompt'></input>",
show: function(config) {
var myConf = sw.MessageBox.config = {
type:'message',
modal:true,
width: 240,
id:'sugarMsgWindow',
close:true,
title:"Alert",
msg: " ",
buttons: [ ]
};
if (config['type'] && config['type'] == "prompt") {
myConf['buttons'] = [{
text: SUGAR.language.get("app_strings", "LBL_EMAIL_CANCEL"), handler:YAHOO.SUGAR.MessageBox.hide
},{
text: SUGAR.language.get("app_strings", "LBL_EMAIL_OK"), handler:config['fn'] ?
function(){
var returnValue = config['fn'](YAHOO.util.Dom.get("sugar-message-prompt").value);
if (typeof(returnValue) == "undefined" || returnValue) {
YAHOO.SUGAR.MessageBox.hide();
} // if
}
: YAHOO.SUGAR.MessageBox.hide, isDefault:true
}];
} else if ((config['type'] && config['type'] == "alert")) {
myConf['buttons'] = [{
text: SUGAR.language.get("app_strings", "LBL_EMAIL_OK"),
handler: config['fn'] ?
function(){YAHOO.SUGAR.MessageBox.hide(); config['fn']();}
:
YAHOO.SUGAR.MessageBox.hide,
isDefault:true
}]
} else if((config['type'] && config['type'] == "confirm")) {
myConf['buttons'] = [{
text: SUGAR.language.get("app_strings", "LBL_EMAIL_YES"), handler:config['fn'] ?
function(){config['fn']('yes');YAHOO.SUGAR.MessageBox.hide();}
: YAHOO.SUGAR.MessageBox.hide, isDefault:true
},{
text: SUGAR.language.get("app_strings", "LBL_EMAIL_NO"), handler:config['fn'] ?
function(){config['fn']('no');YAHOO.SUGAR.MessageBox.hide();}
: YAHOO.SUGAR.MessageBox.hide
}];
}
else if((config['type'] && config['type'] == "plain")) {
myConf['buttons'] = [];
} // else if
for (var i in config) {
myConf[i] = config[i];
}
if (sw.MessageBox.panel) {
sw.MessageBox.panel.destroy();
}
sw.MessageBox.panel = new YAHOO.widget.SimpleDialog(myConf.id, {
width: myConf.width + 'px',
close: myConf.close,
modal: myConf.modal,
visible: true,
fixedcenter: true,
constraintoviewport: true,
draggable: true,
buttons: myConf.buttons
});
if (myConf.type == "progress") {
sw.MessageBox.panel.setBody(sw.MessageBox.progressTemplate.replace(/\{body\}/gi, myConf.msg));
} else if (myConf.type == "prompt") {
sw.MessageBox.panel.setBody(sw.MessageBox.promptTemplate.replace(/\{body\}/gi, myConf.msg));
} else if (myConf.type == "confirm") {
sw.MessageBox.panel.setBody(myConf.msg);
} else {
sw.MessageBox.panel.setBody(myConf.msg);
}
sw.MessageBox.panel.setHeader(myConf.title);
if (myConf.beforeShow) {
sw.MessageBox.panel.beforeShowEvent.subscribe(function() {myConf.beforeShow();});
} // if
if (myConf.beforeHide) {
sw.MessageBox.panel.beforeHideEvent.subscribe(function() {myConf.beforeHide();});
} // if
sw.MessageBox.panel.render(document.body);
sw.MessageBox.panel.show();
},
updateProgress: function(percent, message) {
if (!sw.MessageBox.config.type == "progress") return;
if (typeof message == "string") {
sw.MessageBox.panel.setBody(sw.MessageBox.progressTemplate.replace(/\{body\}/gi, message));
}
var barEl = Dom.getElementsByClassName("sugar-progress-bar", null, YAHOO.SUGAR.MessageBox.panel.element)[0];
if (percent > 100)
percent = 100;
else if (percent < 0)
percent = 0;
barEl.style.width = percent + "%";
},
hide: function() {
if (sw.MessageBox.panel)
sw.MessageBox.panel.hide();
}
};
sw.Template = function(content) {
this._setContent(content);
};
sw.Template.prototype = {
regex : /\{([\w\.]*)\}/gim,
append: function (target, args) {
var tEl = Dom.get(target);
if (tEl) tEl.innerHTML += this.exec(args);
else if (!SUGAR.isIE) console.log("Warning, unable to find target:" + target);
},
exec : function (args) {
var out = this.content;
for (var i in this.vars) {
var val = this._getValue(i, args);
var reg = new RegExp("\\{" + i + "\\}", "g");
out = out.replace(reg, val);
}
return out;
},
_setContent : function(content) {
this.content = content;
var lastIndex = -1;
var result = this.regex.exec(content);
this.vars = { };
while(result && result.index > lastIndex){
lastIndex = result.index;
this.vars[result[1]] = true;
result = this.regex.exec(content);
}
},
_getValue: function(v, scope) {
return function(e) {return eval("this." + e);}.call(scope, v);
}
};
/**
* SelectionGrid is simply a YUI Data Table with row selection already enabled.
*/
sw.SelectionGrid = function(containerEl, columns, dataSource, config){
sw.SelectionGrid.superclass.constructor.call(this, containerEl, columns, dataSource, config);
// Subscribe to events for row selection
this.subscribe("rowMouseoverEvent", this.onEventHighlightRow);
this.subscribe("rowMouseoutEvent", this.onEventUnhighlightRow);
this.subscribe("rowClickEvent", this.onEventSelectRow);
// Programmatically select the first row
this.selectRow(this.getTrEl(0));
// Programmatically bring focus to the instance so arrow selection works immediately
this.focus();
}
YAHOO.extend(sw.SelectionGrid, YAHOO.widget.ScrollingDataTable, {
//Bugfix, the default getColumn will fail if a th element is passed in. http://yuilibrary.com/projects/yui2/ticket/2528034
getColumn : function(column) {
var oColumn = this._oColumnSet.getColumn(column);
if(!oColumn) {
// Validate TD element
var elCell = this.getTdEl(column);
if(elCell && (!column.tagName || column.tagName.toUpperCase() != "TH")) {
oColumn = this._oColumnSet.getColumn(elCell.cellIndex);
}
// Validate TH element
else {
elCell = this.getThEl(column);
if(elCell) {
// Find by TH el ID
var allColumns = this._oColumnSet.flat;
for(var i=0, len=allColumns.length; i<len; i++) {
if(allColumns[i].getThEl().id === elCell.id) {
oColumn = allColumns[i];
}
}
}
}
}
if(!oColumn) {
YAHOO.log("Could not get Column for column at " + column, "info", this.toString());
}
return oColumn;
}
});
/**
* DragDropTable is a YUI Data Table with support for drag/drop row re-ordering.
*/
sw.DragDropTable = function(containerEl, columns, dataSource, config){
var DDT = sw.DragDropTable;
DDT.superclass.constructor.call(this, containerEl, columns, dataSource, config);
this.DDGroup = config.group ? config.group : "defGroup";
//Add table to the dragdrop table groups
if (typeof DDT.groups[this.DDGroup] == "undefined")
DDT.groups[this.DDGroup] = [];
DDT.groups[this.DDGroup][DDT.groups[this.DDGroup].length] = this;
this.tabledd = new YAHOO.util.DDTarget(containerEl);
}
sw.DragDropTable.groups = {
defGroup: []
}
YAHOO.extend(sw.DragDropTable, YAHOO.widget.ScrollingDataTable, {
_addTrEl : function (oRecord) {
var elTr = sw.DragDropTable.superclass._addTrEl.call(this, oRecord);
if (!this.disableEmptyRows || (
oRecord.getData()[this.getColumnSet().keys[0].key] != false
&& oRecord.getData()[this.getColumnSet().keys[0].key] != "")
) {
var _rowDD = new sw.RowDD(this, oRecord, elTr);
}
return elTr;
},
getGroup : function () {
return sw.DragDropTable.groups[this.DDGroup];
}
});
/**
* subclass of DragDrop to allow rows to be picked up and dropped between other rows.
*/
sw.RowDD = function(oDataTable, oRecord, elTr) {
if(oDataTable && oRecord && elTr) {
//sw.RowDD.superclass.constructor.call(this, elTr);
this.ddtable = oDataTable;
this.table = oDataTable.getTableEl();
this.row = oRecord;
this.rowEl = elTr;
this.newIndex = null;
this.init(elTr);
this.initFrame(); // Needed for DDProxy
this.invalidHandleTypes = {};
}
};
YAHOO.extend(sw.RowDD, YAHOO.util.DDProxy, {
// _removeIdRegex : /(<.[^\/<]*)id\s*=\s*['|"]?\w*['|"]?([^>]*>)/gim,
_removeIdRegex : new RegExp("(<.[^\\/<]*)id\\s*=\\s*['|\"]?\w*['|\"]?([^>]*>)", "gim"),
_resizeProxy: function() {
this.constructor.superclass._resizeProxy.apply(this, arguments);
var dragEl = this.getDragEl(),
el = this.getEl();
Dom.setStyle(this.pointer, 'height', (this.rowEl.offsetHeight + 5) + 'px');
Dom.setStyle(this.pointer, 'display', 'block');
var xy = Dom.getXY(el);
Dom.setXY(this.pointer, [xy[0], (xy[1] - 5)]);
Dom.setStyle(dragEl, 'height', this.rowEl.offsetHeight + "px");
Dom.setStyle(dragEl, 'width', (parseInt(Dom.getStyle(dragEl, 'width'),10) + 4) + 'px');
Dom.setXY(this.dragEl, xy);
},
startDrag: function(x, y) {
var dragEl = this.getDragEl();
var clickEl = this.getEl();
Dom.setStyle(clickEl, "opacity", "0.25");
var tableWrap = false;
if (clickEl.tagName.toUpperCase() == "TR")
tableWrap = true;
dragEl.innerHTML = "<table>" + clickEl.innerHTML.replace(this._removeIdRegex, "$1$2") + "</table>";
//Dom.setStyle(dragEl, "color", Dom.getStyle(clickEl, "color"));
Dom.addClass(dragEl, "yui-dt-liner");
Dom.setStyle(dragEl, "height", (clickEl.clientHeight - 2) + "px");
Dom.setStyle(dragEl, "backgroundColor", Dom.getStyle(clickEl, "backgroundColor"));
Dom.setStyle(dragEl, "border", "2px solid gray");
Dom.setStyle(dragEl, "display", "");
this.newTable = this.ddtable;
},
clickValidator: function(e) {
if (this.row.getData()[0] == " ")
return false;
var target = Event.getTarget(e);
return ( this.isValidHandleChild(target) &&
(this.id == this.handleElId || this.DDM.handleWasClicked(target, this.id)) );
},
/**
* This funciton checks that the target of the drag is a table row in this
* DDGroup and simply moves the sourceEL to that location as a preview.
*/
onDragOver: function(ev, id) {
var groupTables = this.ddtable.getGroup();
for(i in groupTables) {
var targetTable = groupTables[i];
if (!targetTable.getContainerEl)
continue;
//We got a table id
if (targetTable.getContainerEl().id == id) {
if (targetTable != this.newTable) { // Moved from one table to another
this.newIndex = targetTable.getRecordSet().getLength() - 1;
var destEl = Dom.get(targetTable.getLastTrEl());
destEl.parentNode.insertBefore(this.getEl(), destEl);
}
this.newTable = targetTable
return true;
}
}
if (this.newTable && this.newTable.getRecord(id)) { // Found the target row
var targetRow = this.newTable.getRecord(id);
var destEl = Dom.get(id);
destEl.parentNode.insertBefore(this.getEl(), destEl);
this.newIndex = this.newTable.getRecordIndex(targetRow);
}
},
endDrag: function() {
//Ensure the element is back on the home table to be cleaned up.
if (this.newTable != null && this.newIndex != null) {
this.getEl().style.display = "none";
this.table.appendChild(this.getEl());
this.newTable.addRow(this.row.getData(), this.newIndex);
this.ddtable.deleteRow(this.row);
this.ddtable.render();
}
this.newTable = this.newIndex = null
var clickEl = this.getEl();
Dom.setStyle(clickEl, "opacity", "");
}
});
/**
* A YUI panel that supports loading and re-loading it's contents from an Asynch request.
*/
sw.AsyncPanel = function (el, params) {
if (params)
sw.AsyncPanel.superclass.constructor.call(this, el, params);
else
sw.AsyncPanel.superclass.constructor.call(this, el);
}
YAHOO.extend(sw.AsyncPanel, YAHOO.widget.Panel, {
loadingText : "Loading...",
failureText : "Error loading content.",
load : function(url, method) {
method = method ? method : "GET";
this.setBody(this.loadingText);
if (Connect.url) url = Connect.url + "&" + url;
Connect.asyncRequest(method, url, {success:this._updateContent, failure:this._loadFailed, scope:this});
},
_updateContent : function (o) {
//Under safari, the width of the panel may expand for no apparent reason, and under FF it will contract
var w = this.cfg.config.width.value + "px";
this.setBody(o.responseText);
if (!SUGAR.isIE)
this.body.style.width = w
},
_loadFailed : function(o) {
this.setBody(this.failureText);
}
});
sw.ClosableTab = function(el, parent, conf) {
this.closeEvent = new YAHOO.util.CustomEvent("close", this);
if (conf)
sw.ClosableTab.superclass.constructor.call(this, el, conf);
else
sw.ClosableTab.superclass.constructor.call(this, el);
this.setAttributeConfig("TabView", {
value: parent
});
this.get("labelEl").parentNode.href = "javascript:void(0);";
}
YAHOO.extend(sw.ClosableTab, YAHOO.widget.Tab, {
close : function () {
this.closeEvent.fire();
var parent = this.get("TabView");
parent.removeTab(this);
},
initAttributes: function(attr) {
sw.ClosableTab.superclass.initAttributes.call(this, attr);
/**
* The message to display when closing the tab
* @attribute closeMsg
* @type String
*/
this.setAttributeConfig("closeMsg", {
value: attr.closeMsg || ""
});
/**
* The tab's label text (or innerHTML).
* @attribute label
* @type String
*/
this.setAttributeConfig("label", {
value: attr.label || this._getLabel(),
method: function(value) {
var labelEl = this.get("labelEl");
if (!labelEl) { // create if needed
this.set(LABEL_EL, this._createLabelEl());
}
labelEl.innerHTML = value;
var closeButton = document.createElement('a');
closeButton.href = "javascript:void(0);";
Dom.addClass(closeButton, "sugar-tab-close");
Event.addListener(closeButton, "click", function(e, tab){
if (tab.get("closeMsg") != "")
{
if (confirm(tab.get("closeMsg"))) {
tab.close();
}
}
else {
tab.close();
}
},
this
);
labelEl.appendChild(closeButton);
}
});
}
});
/**
* The sugar Tree is a YUI tree with node construction based on AJAX data built in.
*/
sw.Tree = function (parentEl, baseRequestParams, rootParams) {
this.baseRequestParams = baseRequestParams;
sw.Tree.superclass.constructor.call(this, parentEl);
if (rootParams) {
if (typeof rootParams == "string")
this.sendTreeNodeDataRequest(this.getRoot(), rootParams);
else
this.sendTreeNodeDataRequest(this.getRoot(), "");
}
}
YAHOO.extend(sw.Tree, YAHOO.widget.TreeView, {
sendTreeNodeDataRequest: function(parentNode, params){
YAHOO.util.Connect.asyncRequest('POST', 'index.php', {
success: this.handleTreeNodeDataRequest,
argument: {
parentNode: parentNode
},
scope: this
}, this.baseRequestParams + params);
},
handleTreeNodeDataRequest : function(o) {
var parentNode = o.argument.parentNode;
//parent.tree.removeChildren(parentNode);
var resp = YAHOO.lang.JSON.parse(o.responseText);
if (resp.tree_data.nodes) {
for (var i = 0; i < resp.tree_data.nodes.length; i++) {
var newChild = this.buildTreeNodeRecursive(resp.tree_data.nodes[i], parentNode);
}
}
parentNode.tree.draw();
},
buildTreeNodeRecursive : function(nodeData, parentNode) {
nodeData.label = nodeData.text;
var node = new YAHOO.widget.TextNode(nodeData, parentNode, nodeData.expanded);
if (typeof(nodeData.children) == 'object') {
for (var i = 0; i < nodeData.children.length; i++) {
this.buildTreeNodeRecursive(nodeData.children[i], node);
}
}
return node;
}
});
/**
* A 1/2 second fade-in animation.
* @class TVSlideIn
* @constructor
* @param el {HTMLElement} the element to animate
* @param callback {function} function to invoke when the animation is finished
*/
YAHOO.widget.TVSlideIn = function(el, callback) {
/**
* The element to animate
* @property el
* @type HTMLElement
*/
this.el = el;
/**
* the callback to invoke when the animation is complete
* @property callback
* @type function
*/
this.callback = callback;
this.logger = new YAHOO.widget.LogWriter(this.toString());
};
YAHOO.widget.TVSlideIn.prototype = {
/**
* Performs the animation
* @method animate
*/
animate: function() {
var tvanim = this;
var s = this.el.style;
s.height = "";
s.display = "";
s.overflow = "hidden";
var th = this.el.clientHeight;
s.height = "0px";
var dur = 0.4;
var a = new YAHOO.util.Anim(this.el, {height: {from: 0, to: th, unit:"px"}}, dur);
a.onComplete.subscribe( function() { tvanim.onComplete(); } );
a.animate();
},
/**
* Clean up and invoke callback
* @method onComplete
*/
onComplete: function() {
this.el.style.overflow = "";
this.el.style.height = "";
this.callback();
},
/**
* toString
* @method toString
* @return {string} the string representation of the instance
*/
toString: function() {
return "TVSlideIn";
}
};
/**
* A 1/2 second fade out animation.
* @class TVSlideOut
* @constructor
* @param el {HTMLElement} the element to animate
* @param callback {Function} function to invoke when the animation is finished
*/
YAHOO.widget.TVSlideOut = function(el, callback) {
/**
* The element to animate
* @property el
* @type HTMLElement
*/
this.el = el;
/**
* the callback to invoke when the animation is complete
* @property callback
* @type function
*/
this.callback = callback;
this.logger = new YAHOO.widget.LogWriter(this.toString());
};
YAHOO.widget.TVSlideOut.prototype = {
/**
* Performs the animation
* @method animate
*/
animate: function() {
var tvanim = this;
var dur = 0.4;
var th = this.el.clientHeight;
this.el.style.overflow = "hidden";
var a = new YAHOO.util.Anim(this.el, {height: {from: th, to: 0, unit:"px"}}, dur);
a.onComplete.subscribe( function() { tvanim.onComplete(); } );
a.animate();
},
/**
* Clean up and invoke callback
* @method onComplete
*/
onComplete: function() {
var s = this.el.style;
s.display = "none";
this.el.style.overflow = "";
this.el.style.height = "";
this.callback();
},
/**
* toString
* @method toString
* @return {string} the string representation of the instance
*/
toString: function() {
return "TVSlideOut";
}
};
})();

View File

@@ -0,0 +1,265 @@
/**
* SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
*
* SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*/
if(typeof deconcept == "undefined") var deconcept = new Object();
if(typeof deconcept.util == "undefined") deconcept.util = new Object();
if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
deconcept.SWFObject = function(swf, id, w, h, ver, c, quality, xiRedirectUrl, redirectUrl, detectKey) {
if (!document.getElementById) { return; }
this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
this.params = new Object();
this.variables = new Object();
this.attributes = new Array();
if(swf) { this.setAttribute('swf', swf); }
if(id) { this.setAttribute('id', id); }
if(w) { this.setAttribute('width', w); }
if(h) { this.setAttribute('height', h); }
if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion();
if (!window.opera && document.all && this.installedVer.major > 7) {
// only add the onunload cleanup if the Flash Player version supports External Interface and we are in IE
deconcept.SWFObject.doPrepUnload = true;
}
if(c) { this.addParam('bgcolor', c); }
var q = quality ? quality : 'high';
this.addParam('quality', q);
this.setAttribute('useExpressInstall', false);
this.setAttribute('doExpressInstall', false);
var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
this.setAttribute('xiRedirectUrl', xir);
this.setAttribute('redirectUrl', '');
if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
}
deconcept.SWFObject.prototype = {
useExpressInstall: function(path) {
this.xiSWFPath = !path ? "expressinstall.swf" : path;
this.setAttribute('useExpressInstall', true);
},
setAttribute: function(name, value){
this.attributes[name] = value;
},
getAttribute: function(name){
return this.attributes[name];
},
addParam: function(name, value){
this.params[name] = value;
},
getParams: function(){
return this.params;
},
addVariable: function(name, value){
this.variables[name] = value;
},
getVariable: function(name){
return this.variables[name];
},
getVariables: function(){
return this.variables;
},
getVariablePairs: function(){
var variablePairs = new Array();
var key;
var variables = this.getVariables();
for(key in variables){
variablePairs[variablePairs.length] = key +"="+ variables[key];
}
return variablePairs;
},
getSWFHTML: function() {
var swfNode = "";
if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
if (this.getAttribute("doExpressInstall")) {
this.addVariable("MMplayerType", "PlugIn");
this.setAttribute('swf', this.xiSWFPath);
}
swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'" style="'+ this.getAttribute('style') +'"';
swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
var params = this.getParams();
for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
var pairs = this.getVariablePairs().join("&");
if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
swfNode += '/>';
} else { // PC IE
if (this.getAttribute("doExpressInstall")) {
this.addVariable("MMplayerType", "ActiveX");
this.setAttribute('swf', this.xiSWFPath);
}
swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'" style="'+ this.getAttribute('style') +'">';
swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
var params = this.getParams();
for(var key in params) {
swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
}
var pairs = this.getVariablePairs().join("&");
if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
swfNode += "</object>";
}
return swfNode;
},
write: function(elementId){
if(this.getAttribute('useExpressInstall')) {
// check to see if we need to do an express install
var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
this.setAttribute('doExpressInstall', true);
this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
document.title = document.title.slice(0, 47) + " - Flash Player Installation";
this.addVariable("MMdoctitle", document.title);
}
}
if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
n.innerHTML = this.getSWFHTML();
return true;
}else{
if(this.getAttribute('redirectUrl') != "") {
document.location.replace(this.getAttribute('redirectUrl'));
}
}
return false;
}
}
/* ---- detection functions ---- */
deconcept.SWFObjectUtil.getPlayerVersion = function(){
var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
if(navigator.plugins && navigator.mimeTypes.length){
var x = navigator.plugins["Shockwave Flash"];
if(x && x.description) {
PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
}
}else if (navigator.userAgent && navigator.userAgent.indexOf("Windows CE") >= 0){ // if Windows CE
var axo = 1;
var counter = 3;
while(axo) {
try {
counter++;
axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+ counter);
// document.write("player v: "+ counter);
PlayerVersion = new deconcept.PlayerVersion([counter,0,0]);
} catch (e) {
axo = null;
}
}
} else { // Win IE (non mobile)
// do minor version lookup in IE, but avoid fp6 crashing issues
// see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
try{
var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
}catch(e){
try {
var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
PlayerVersion = new deconcept.PlayerVersion([6,0,21]);
axo.AllowScriptAccess = "always"; // error if player version < 6.0.47 (thanks to Michael Williams @ Adobe for this code)
} catch(e) {
if (PlayerVersion.major == 6) {
return PlayerVersion;
}
}
try {
axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
} catch(e) {}
}
if (axo != null) {
PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
}
}
return PlayerVersion;
}
deconcept.PlayerVersion = function(arrVersion){
this.major = arrVersion[0] != null ? parseInt(arrVersion[0]) : 0;
this.minor = arrVersion[1] != null ? parseInt(arrVersion[1]) : 0;
this.rev = arrVersion[2] != null ? parseInt(arrVersion[2]) : 0;
}
deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
if(this.major < fv.major) return false;
if(this.major > fv.major) return true;
if(this.minor < fv.minor) return false;
if(this.minor > fv.minor) return true;
if(this.rev < fv.rev) return false;
return true;
}
/* ---- get value of query string param ---- */
deconcept.util = {
getRequestParameter: function(param) {
var q = document.location.search || document.location.hash;
if (param == null) { return q; }
if(q) {
var pairs = q.substring(1).split("&");
for (var i=0; i < pairs.length; i++) {
if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
return pairs[i].substring((pairs[i].indexOf("=")+1));
}
}
}
return "";
}
}
/* fix for video streaming bug */
deconcept.SWFObjectUtil.cleanupSWFs = function() {
var objects = document.getElementsByTagName("OBJECT");
for (var i = objects.length - 1; i >= 0; i--) {
objects[i].style.display = 'none';
for (var x in objects[i]) {
if (typeof objects[i][x] == 'function') {
objects[i][x] = function(){};
}
}
}
}
// fixes bug in some fp9 versions see http://blog.deconcept.com/2006/07/28/swfobject-143-released/
if (deconcept.SWFObject.doPrepUnload) {
if (!deconcept.unloadSet) {
deconcept.SWFObjectUtil.prepUnload = function() {
__flash_unloadHandler = function(){};
__flash_savedUnloadHandler = function(){};
window.attachEvent("onunload", deconcept.SWFObjectUtil.cleanupSWFs);
}
window.attachEvent("onbeforeunload", deconcept.SWFObjectUtil.prepUnload);
deconcept.unloadSet = true;
}
}
/* add document.getElementById if needed (mobile IE < 5) */
if (!document.getElementById && document.all) { document.getElementById = function(id) { return document.all[id]; }}
/* add some aliases for ease of use/backwards compatibility */
var getQueryParamValue = deconcept.util.getRequestParameter;
var FlashObject = deconcept.SWFObject; // for legacy support
var SWFObject = deconcept.SWFObject;
/* begin SUGARCRM customization */
function loadChartSWF(chartName, xmlFile, width, height, stylesheet, colorscheme, langFile){
if(!document.getElementById(chartName + '_div')) {
return;
}
if (width == '100%'){
width = document.getElementById(chartName + '_div').clientWidth;
}
else{
width = width.replace(/px/,'');
}
height = height.replace(/px/,'');
var home = new SWFObject("include/SugarCharts/swf/chart.swf", chartName, "100%", "100%", "7");
home.addParam("wmode","transparent");
home.addParam("menu","false");
home.addParam("quality","high");
home.addVariable( "inputFile" , xmlFile)
home.addVariable( "swfLocation" ,"include/SugarCharts/swf/");
home.addVariable( "inputColorScheme" , colorscheme);
home.addVariable( "inputStyleSheet", stylesheet);
home.addVariable( "inputLanguage", langFile);
home.addVariable( "myWidth", width);
home.addVariable( "myHeight", height);
home.write(chartName + '_div');
}
/* end SUGARCRM customization */

View File

@@ -0,0 +1,805 @@
/**
* Code Syntax Highlighter.
* Version 1.3.0
* Copyright (C) 2004 Alex Gorbatchev.
* http://www.dreamprojections.com/syntaxhighlighter/
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//
// create namespaces
//
var dp = {
sh : // dp.sh
{
Utils : {}, // dp.sh.Utils
Brushes : {}, // dp.sh.Brushes
Strings : {},
Version : '1.3.0'
}
};
dp.sh.Strings = {
AboutDialog : '<html><head><title>About...</title></head><body class="dp-about"><table cellspacing="0"><tr><td class="copy"><p class="title">dp.SyntaxHighlighter</div><div class="para">Version: {V}</p><p><a href="http://www.dreamprojections.com/syntaxhighlighter/?ref=about" target="_blank">http://www.dreamprojections.com/SyntaxHighlighter</a></p>&copy;2004-2005 Alex Gorbatchev. All right reserved.</td></tr><tr><td class="footer"><input type="button" class="close" value="OK" onClick="window.close()"/></td></tr></table></body></html>',
// tools
ExpandCode : '+ expand code',
ViewPlain : 'view plain',
Print : 'print',
CopyToClipboard : 'copy to clipboard',
About : '?',
CopiedToClipboard : 'The code is in your clipboard now.'
};
dp.SyntaxHighlighter = dp.sh;
//
// Dialog and toolbar functions
//
dp.sh.Utils.Expand = function(sender)
{
var table = sender;
var span = sender;
// find the span in which the text label and pipe contained so we can hide it
while(span != null && span.tagName != 'SPAN')
span = span.parentNode;
// find the table
while(table != null && table.tagName != 'TABLE')
table = table.parentNode;
// remove the 'expand code' button
span.parentNode.removeChild(span);
table.tBodies[0].className = 'show';
table.parentNode.style.height = '100%'; // containing div isn't getting updated properly when the TBODY is shown
}
// opens a new windows and puts the original unformatted source code inside.
dp.sh.Utils.ViewSource = function(sender)
{
var code = sender.parentNode.originalCode;
var wnd = window.open('', '_blank', 'width=750, height=400, location=0, resizable=1, menubar=0, scrollbars=1');
code = code.replace(/</g, '&lt;');
wnd.document.write('<pre>' + code + '</pre>');
wnd.document.close();
}
// copies the original source code in to the clipboard (IE only)
dp.sh.Utils.ToClipboard = function(sender)
{
var code = sender.parentNode.originalCode;
// This works only for IE. There's a way to make it work with Mozilla as well,
// but it requires security settings changed on the client, which isn't by
// default, so 99% of users won't have it working anyways.
if(window.clipboardData)
{
window.clipboardData.setData('text', code);
alert(dp.sh.Strings.CopiedToClipboard);
}
}
// creates an invisible iframe, puts the original source code inside and prints it
dp.sh.Utils.PrintSource = function(sender)
{
var td = sender.parentNode;
var code = td.processedCode;
var iframe = document.createElement('IFRAME');
var doc = null;
var wnd =
// this hides the iframe
iframe.style.cssText = 'position:absolute; width:0px; height:0px; left:-5px; top:-5px;';
td.appendChild(iframe);
doc = iframe.contentWindow.document;
code = code.replace(/</g, '&lt;');
doc.open();
doc.write('<pre>' + code + '</pre>');
doc.close();
iframe.contentWindow.focus();
iframe.contentWindow.print();
td.removeChild(iframe);
}
dp.sh.Utils.About = function()
{
var wnd = window.open('', '_blank', 'dialog,width=320,height=150,scrollbars=0');
var doc = wnd.document;
var styles = document.getElementsByTagName('style');
var links = document.getElementsByTagName('link');
doc.write(dp.sh.Strings.AboutDialog.replace('{V}', dp.sh.Version));
// copy over ALL the styles from the parent page
for(var i = 0; i < styles.length; i++)
doc.write('<style>' + styles[i].innerHTML + '</style>');
for(var i = 0; i < links.length; i++)
if(links[i].rel.toLowerCase() == 'stylesheet')
doc.write('<link type="text/css" rel="stylesheet" href="' + links[i].href + '"></link>');
doc.close();
wnd.focus();
}
//
// Match object
//
dp.sh.Match = function(value, index, css)
{
this.value = value;
this.index = index;
this.length = value.length;
this.css = css;
}
//
// Highlighter object
//
dp.sh.Highlighter = function()
{
this.addGutter = true;
this.addControls = true;
this.collapse = false;
this.tabsToSpaces = true;
}
// static callback for the match sorting
dp.sh.Highlighter.SortCallback = function(m1, m2)
{
// sort matches by index first
if(m1.index < m2.index)
return -1;
else if(m1.index > m2.index)
return 1;
else
{
// if index is the same, sort by length
if(m1.length < m2.length)
return -1;
else if(m1.length > m2.length)
return 1;
}
return 0;
}
// gets a list of all matches for a given regular expression
dp.sh.Highlighter.prototype.GetMatches = function(regex, css)
{
var index = 0;
var match = null;
while((match = regex.exec(this.code)) != null)
{
this.matches[this.matches.length] = new dp.sh.Match(match[0], match.index, css);
}
}
dp.sh.Highlighter.prototype.AddBit = function(str, css)
{
var span = document.createElement('span');
str = str.replace(/&/g, '&amp;');
str = str.replace(/ /g, '&nbsp;');
str = str.replace(/</g, '&lt;');
str = str.replace(/\n/gm, '&nbsp;<br>');
// when adding a piece of code, check to see if it has line breaks in it
// and if it does, wrap individual line breaks with span tags
if(css != null)
{
var regex = new RegExp('<br>', 'gi');
if(regex.test(str))
{
var lines = str.split('&nbsp;<br>');
str = '';
for(var i = 0; i < lines.length; i++)
{
span = document.createElement('SPAN');
span.className = css;
span.innerHTML = lines[i];
this.div.appendChild(span);
// don't add a <BR> for the last line
if(i + 1 < lines.length)
this.div.appendChild(document.createElement('BR'));
}
}
else
{
span.className = css;
span.innerHTML = str;
this.div.appendChild(span);
}
}
else
{
span.innerHTML = str;
this.div.appendChild(span);
}
}
// checks if one match is inside any other match
dp.sh.Highlighter.prototype.IsInside = function(match)
{
if(match == null || match.length == 0)
return;
for(var i = 0; i < this.matches.length; i++)
{
var c = this.matches[i];
if(c == null)
continue;
if((match.index > c.index) && (match.index <= c.index + c.length))
return true;
}
return false;
}
dp.sh.Highlighter.prototype.ProcessRegexList = function()
{
for(var i = 0; i < this.regexList.length; i++)
this.GetMatches(this.regexList[i].regex, this.regexList[i].css);
}
dp.sh.Highlighter.prototype.ProcessSmartTabs = function(code)
{
var lines = code.split('\n');
var result = '';
var tabSize = 4;
var tab = '\t';
// This function inserts specified amount of spaces in the string
// where a tab is while removing that given tab.
function InsertSpaces(line, pos, count)
{
var left = line.substr(0, pos);
var right = line.substr(pos + 1, line.length); // pos + 1 will get rid of the tab
var spaces = '';
for(var i = 0; i < count; i++)
spaces += ' ';
return left + spaces + right;
}
// This function process one line for 'smart tabs'
function ProcessLine(line, tabSize)
{
if(line.indexOf(tab) == -1)
return line;
var pos = 0;
while((pos = line.indexOf(tab)) != -1)
{
// This is pretty much all there is to the 'smart tabs' logic.
// Based on the position within the line and size of a tab,
// calculate the amount of spaces we need to insert.
var spaces = tabSize - pos % tabSize;
line = InsertSpaces(line, pos, spaces);
}
return line;
}
// Go through all the lines and do the 'smart tabs' magic.
for(var i = 0; i < lines.length; i++)
result += ProcessLine(lines[i], tabSize) + '\n';
return result;
}
dp.sh.Highlighter.prototype.SwitchToTable = function()
{
// thanks to Lachlan Donald from SitePoint.com for this <br/> tag fix.
var html = this.div.innerHTML.replace(/<(br)\/?>/gi, '\n');
var lines = html.split('\n');
var row = null;
var cell = null;
var tBody = null;
var html = '';
var pipe = ' | ';
// creates an anchor to a utility
function UtilHref(util, text)
{
return '<a href="#" onclick="dp.sh.Utils.' + util + '(this); return false;">' + text + '</a>';
}
tBody = document.createElement('TBODY'); // can be created and all others go to tBodies collection.
this.table.appendChild(tBody);
if(this.addGutter == true)
{
row = tBody.insertRow(-1);
cell = row.insertCell(-1);
cell.className = 'tools-corner';
}
if(this.addControls == true)
{
var tHead = document.createElement('THEAD'); // controls will be placed in here
this.table.appendChild(tHead);
row = tHead.insertRow(-1);
// add corner if there's a gutter
if(this.addGutter == true)
{
cell = row.insertCell(-1);
cell.className = 'tools-corner';
}
cell = row.insertCell(-1);
// preserve some variables for the controls
cell.originalCode = this.originalCode;
cell.processedCode = this.code;
cell.className = 'tools';
if(this.collapse == true)
{
tBody.className = 'hide';
cell.innerHTML += '<span><b>' + UtilHref('Expand', dp.sh.Strings.ExpandCode) + '</b>' + pipe + '</span>';
}
cell.innerHTML += UtilHref('ViewSource', dp.sh.Strings.ViewPlain) + pipe + UtilHref('PrintSource', dp.sh.Strings.Print);
// IE has this clipboard object which is easy enough to use
if(window.clipboardData)
cell.innerHTML += pipe + UtilHref('ToClipboard', dp.sh.Strings.CopyToClipboard);
cell.innerHTML += pipe + UtilHref('About', dp.sh.Strings.About);
}
for(var i = 0, lineIndex = this.firstLine; i < lines.length - 1; i++, lineIndex++)
{
row = tBody.insertRow(-1);
if(this.addGutter == true)
{
cell = row.insertCell(-1);
cell.className = 'gutter';
cell.innerHTML = lineIndex;
}
cell = row.insertCell(-1);
cell.className = 'line' + (i % 2 + 1); // uses .line1 and .line2 css styles for alternating lines
cell.innerHTML = lines[i];
}
this.div.innerHTML = '';
}
dp.sh.Highlighter.prototype.Highlight = function(code)
{
function Trim(str)
{
return str.replace(/^\s*(.*?)[\s\n]*$/g, '$1');
}
function Chop(str)
{
return str.replace(/\n*$/, '').replace(/^\n*/, '');
}
function Unindent(str)
{
var lines = str.split('\n');
var indents = new Array();
var regex = new RegExp('^\\s*', 'g');
var min = 1000;
// go through every line and check for common number of indents
for(var i = 0; i < lines.length && min > 0; i++)
{
if(Trim(lines[i]).length == 0)
continue;
var matches = regex.exec(lines[i]);
if(matches != null && matches.length > 0)
min = Math.min(matches[0].length, min);
}
// trim minimum common number of white space from the begining of every line
if(min > 0)
for(var i = 0; i < lines.length; i++)
lines[i] = lines[i].substr(min);
return lines.join('\n');
}
// This function returns a portions of the string from pos1 to pos2 inclusive
function Copy(string, pos1, pos2)
{
return string.substr(pos1, pos2 - pos1);
}
var pos = 0;
this.originalCode = code;
this.code = Chop(Unindent(code));
this.div = document.createElement('DIV');
this.table = document.createElement('TABLE');
this.matches = new Array();
if(this.CssClass != null)
this.table.className = this.CssClass;
// replace tabs with spaces
if(this.tabsToSpaces == true)
this.code = this.ProcessSmartTabs(this.code);
this.table.border = 0;
this.table.cellSpacing = 0;
this.table.cellPadding = 0;
this.ProcessRegexList();
// if no matches found, add entire code as plain text
if(this.matches.length == 0)
{
this.AddBit(this.code, null);
this.SwitchToTable();
return;
}
// sort the matches
this.matches = this.matches.sort(dp.sh.Highlighter.SortCallback);
// The following loop checks to see if any of the matches are inside
// of other matches. This process would get rid of highligting strings
// inside comments, keywords inside strings and so on.
for(var i = 0; i < this.matches.length; i++)
if(this.IsInside(this.matches[i]))
this.matches[i] = null;
// Finally, go through the final list of matches and pull the all
// together adding everything in between that isn't a match.
for(var i = 0; i < this.matches.length; i++)
{
var match = this.matches[i];
if(match == null || match.length == 0)
continue;
this.AddBit(Copy(this.code, pos, match.index), null);
this.AddBit(match.value, match.css);
pos = match.index + match.length;
}
this.AddBit(this.code.substr(pos), null);
this.SwitchToTable();
}
dp.sh.Highlighter.prototype.GetKeywords = function(str)
{
return '\\b' + str.replace(/ /g, '\\b|\\b') + '\\b';
}
// highlightes all elements identified by name and gets source code from specified property
dp.sh.HighlightAll = function(name, showGutter /* optional */, showControls /* optional */, collapseAll /* optional */, firstLine /* optional */)
{
function FindValue()
{
var a = arguments;
for(var i = 0; i < a.length; i++)
{
if(a[i] == null)
continue;
if(typeof(a[i]) == 'string' && a[i] != '')
return a[i] + '';
if(typeof(a[i]) == 'object' && a[i].value != '')
return a[i].value + '';
}
return null;
}
function IsOptionSet(value, list)
{
for(var i = 0; i < list.length; i++)
if(list[i] == value)
return true;
return false;
}
function GetOptionValue(name, list, defaultValue)
{
var regex = new RegExp('^' + name + '\\[(\\w+)\\]$', 'gi');
var matches = null;
for(var i = 0; i < list.length; i++)
if((matches = regex.exec(list[i])) != null)
return matches[1];
return defaultValue;
}
var elements = document.getElementsByName(name);
var highlighter = null;
var registered = new Object();
var propertyName = 'value';
// if no code blocks found, leave
if(elements == null)
return;
// register all brushes
for(var brush in dp.sh.Brushes)
{
var aliases = dp.sh.Brushes[brush].Aliases;
if(aliases == null)
continue;
for(var i = 0; i < aliases.length; i++)
registered[aliases[i]] = brush;
}
for(var i = 0; i < elements.length; i++)
{
var element = elements[i];
var options = FindValue(
element.attributes['class'], element.className,
element.attributes['language'], element.language
);
var language = '';
if(options == null)
continue;
options = options.split(':');
language = options[0].toLowerCase();
if(registered[language] == null)
continue;
// instantiate a brush
highlighter = new dp.sh.Brushes[registered[language]]();
// hide the original element
element.style.display = 'none';
highlighter.addGutter = (showGutter == null) ? !IsOptionSet('nogutter', options) : showGutter;
highlighter.addControls = (showControls == null) ? !IsOptionSet('nocontrols', options) : showControls;
highlighter.collapse = (collapseAll == null) ? IsOptionSet('collapse', options) : collapseAll;
// first line idea comes from Andrew Collington, thanks!
highlighter.firstLine = (firstLine == null) ? parseInt(GetOptionValue('firstline', options, 1)) : firstLine;
highlighter.Highlight(element[propertyName]);
// place the result table inside a div
var div = document.createElement('DIV');
div.className = 'dp-highlighter';
div.appendChild(highlighter.table);
element.parentNode.insertBefore(div, element);
}
}
dp.sh.Brushes.Xml = function()
{
this.CssClass = 'dp-xml';
}
dp.sh.Brushes.Xml.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.Xml.Aliases = ['xml', 'xhtml', 'xslt', 'html', 'xhtml'];
dp.sh.Brushes.Xml.prototype.ProcessRegexList = function()
{
function push(array, value)
{
array[array.length] = value;
}
/* If only there was a way to get index of a group within a match, the whole XML
could be matched with the expression looking something like that:
(<!\[CDATA\[\s*.*\s*\]\]>)
| (<!--\s*.*\s*?-->)
| (<)*(\w+)*\s*(\w+)\s*=\s*(".*?"|'.*?'|\w+)(/*>)*
| (</?)(.*?)(/?>)
*/
var index = 0;
var match = null;
var regex = null;
// Match CDATA in the following format <![ ... [ ... ]]>
// <\!\[[\w\s]*?\[(.|\s)*?\]\]>
this.GetMatches(new RegExp('<\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\]>', 'gm'), 'cdata');
// Match comments
// <!--\s*.*\s*?-->
this.GetMatches(new RegExp('<!--\\s*.*\\s*?-->', 'gm'), 'comments');
// Match attributes and their values
// (\w+)\s*=\s*(".*?"|\'.*?\'|\w+)*
regex = new RegExp('([\\w-\.]+)\\s*=\\s*(".*?"|\'.*?\'|\\w+)*', 'gm');
while((match = regex.exec(this.code)) != null)
{
push(this.matches, new dp.sh.Match(match[1], match.index, 'attribute'));
// if xml is invalid and attribute has no property value, ignore it
if(match[2] != undefined)
{
push(this.matches, new dp.sh.Match(match[2], match.index + match[0].indexOf(match[2]), 'attribute-value'));
}
}
// Match opening and closing tag brackets
// </*\?*(?!\!)|/*\?*>
this.GetMatches(new RegExp('</*\\?*(?!\\!)|/*\\?*>', 'gm'), 'tag');
// Match tag names
// </*\?*\s*(\w+)
regex = new RegExp('</*\\?*\\s*([\\w-\.]+)', 'gm');
while((match = regex.exec(this.code)) != null)
{
push(this.matches, new dp.sh.Match(match[1], match.index + match[0].indexOf(match[1]), 'tag-name'));
}
}
dp.sh.Brushes.Php = function()
{
var keywords = 'and or xor __FILE__ __LINE__ array as break case ' +
'cfunction class const continue declare default die do echo else ' +
'elseif empty enddeclare endfor endforeach endif endswitch endwhile eval exit ' +
'extends for foreach function global if include include_once isset list ' +
'new old_function print require require_once return static switch unset use ' +
'var while __FUNCTION__ __CLASS__';
this.regexList = [
{ regex: new RegExp('//.*$', 'gm'), css: 'comment' }, // one line comments
{ regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'), css: 'comment' }, // multiline comments
{ regex: new RegExp('"(?:[^"\n]|[\"])*?"', 'g'), css: 'string' }, // double quoted strings
{ regex: new RegExp("'(?:[^'\n]|[\'])*?'", 'g'), css: 'string' }, // single quoted strings
{ regex: new RegExp('\\$\\w+', 'g'), css: 'vars' }, // variables
{ regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword' } // keyword
];
this.CssClass = 'dp-c';
}
dp.sh.Brushes.Php.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.Php.Aliases = ['php'];
dp.sh.Brushes.JScript = function()
{
var keywords = 'abstract boolean break byte case catch char class const continue debugger ' +
'default delete do double else enum export extends false final finally float ' +
'for function goto if implements import in instanceof int interface long native ' +
'new null package private protected public return short static super switch ' +
'synchronized this throw throws transient true try typeof var void volatile while with';
this.regexList = [
{ regex: new RegExp('//.*$', 'gm'), css: 'comment' }, // one line comments
{ regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'), css: 'comment' }, // multiline comments
{ regex: new RegExp('"(?:[^"\n]|[\"])*?"', 'g'), css: 'string' }, // double quoted strings
{ regex: new RegExp("'(?:[^'\n]|[\'])*?'", 'g'), css: 'string' }, // single quoted strings
{ regex: new RegExp('^\\s*#.*', 'gm'), css: 'preprocessor' }, // preprocessor tags like #region and #endregion
{ regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword' } // keywords
];
this.CssClass = 'dp-c';
}
dp.sh.Brushes.JScript.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.JScript.Aliases = ['js', 'jscript', 'javascript'];
dp.sh.Brushes.CSS = function() {
//Not used yet - added to values
var tags = 'abbr acronym address applet area a b base basefont bdo big blockquote body br button ' +
'caption center cite code col colgroup dd del dfn dir div dl dt em fieldset form frame frameset h1 h2 h3 h4 h5 h6 head hr html img i ' +
'iframe img input ins isindex kbd label legend li link map menu meta noframes noscript ol optgroup option p param pre q s samp script select ' +
'span strike strong style sub sup table tbody td textarea tfoot th thead title tr tt ul u';
var keywords = 'ascent azimuth background-attachment background-color background-image background-position ' +
'background-repeat background baseline bbox border-collapse border-color border-spacing border-style border-top ' +
'border-right border-bottom border-left border-top-color border-right-color border-bottom-color border-left-color ' +
'border-top-style border-right-style border-bottom-style border-left-style border-top-width border-right-width ' +
'border-bottom-width border-left-width border-width border bottom cap-height caption-side centerline clear clip color ' +
'content counter-increment counter-reset cue-after cue-before cue cursor definition-src descent direction display ' +
'elevation empty-cells float font-size-adjust font-family font-size font-stretch font-style font-variant font-weight font ' +
'height letter-spacing line-height list-style-image list-style-position list-style-type list-style margin-top ' +
'margin-right margin-bottom margin-left margin marker-offset marks mathline max-height max-width min-height min-width orphans ' +
'outline-color outline-style outline-width outline overflow-x overflow-y overflow padding-top padding-right padding-bottom padding-left padding page ' +
'page-break-after page-break-before page-break-inside pause pause-after pause-before pitch pitch-range play-during position ' +
'quotes richness right left bottom top size slope src speak-header speak-numeral speak-punctuation speak speech-rate stemh stemv stress ' +
'table-layout text-align text-decoration text-indent text-shadow text-transform unicode-bidi unicode-range units-per-em ' +
'vertical-align visibility voice-family volume white-space widows width widths word-spacing x-height z-index zoom important after filter opacity';
var values = 'progid:DXImageTransform.Microsoft.AlphaImageLoader src sizingMethod alpha opacity ' +
'above absolute all always aqua armenian attr aural auto avoid baseline behind below bidi-override black blink block blue bold bolder both bottom braille capitalize center center-left center-right circle close-quote code collapse compact condensed '+
'continuous counter counters crop cross crosshair cursive dashed decimal decimal-leading-zero default digits disc dotted double embed embossed e-resize expanded extra-condensed extra-expanded fantasy far-left far-right fast faster fixed format fuchsia '+
'gray green groove handheld hebrew help hidden hide high higher inline-table inline inset inside invert italic justify landscape large larger left-side left leftwards level lighter lime line-through list-item local loud lower-alpha '+
'lowercase lower-greek lower-latin lower-roman lower low ltr marker maroon medium message-box middle mix move narrower navy ne-resize no-close-quote none no-open-quote no-repeat normal nowrap n-resize nw-resize oblique olive once open-quote outset '+
'outside overline pointer portrait print projection purple red relative repeat repeat-x repeat-y rgb ridge right right-side rightwards rtl run-in screen scroll semi-condensed semi-expanded separate se-resize show silent silver slower slow '+
'small small-caps small-caption smaller soft solid speech spell-out square s-resize static status-bar sub super sw-resize table-caption table-cell table-column table-column-group table-footer-group table-header-group table-row table-row-group teal '+
'text-bottom text-top thick thin top transparent tty tv ultra-condensed ultra-expanded underline upper-alpha uppercase upper-latin upper-roman url visible wait white wider w-resize x-fast x-high x-large x-loud x-low x-slow x-small x-soft xx-large xx-small yellow';
this.regexList = [
{ regex: new RegExp('//.*$', 'gm'), css: 'comment' }, // one line comments
{ regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'), css: 'comment' }, // multiline comments
{ regex: new RegExp('"(?:[^"\n]|[\"])*?"', 'g'), css: 'string' }, // double quoted strings
{ regex: new RegExp("'(?:[^'\n]|[\'])*?'", 'g'), css: 'string' }, // single quoted strings
{ regex: new RegExp('^\\s*.*{', 'gm'), css: 'preprocessor' }, // everything before a {
{ regex: new RegExp('}', 'gm'), css: 'preprocessor' }, // The }
{ regex: new RegExp(this.GetKeywordsCSS(keywords), 'gm'), css: 'keyword' }, // keywords
{ regex: new RegExp(this.GetValuesCSS(values), 'gm'), css: 'value' }, // values
{ regex: new RegExp('(-?\\d+)(\.\\d+)?(px|em|pt|\:|\%|)', 'g'), css: 'value' } //Sizes
];
//Not used any more
/*
{ regex: new RegExp('(-?\\d+)(\.\\d+)', 'g'), css: 'value' }, //Plain Numbers
{ regex: new RegExp('(0(?=;))', 'g'), css: 'value' } //Number 0
{ regex: new RegExp('\([.]\)', 'gm'), css: 'string' }, // Things in parenthesis
{ regex: new RegExp('\\#[a-zA-Z0-9]{3,6}', 'g'), css: 'colors' }, // html colors
{ regex: new RegExp(this.GetKeywords(tags), 'g'), css: 'tags' }, // keywords
*/
this.CssClass = 'dp-css';
}
dp.sh.Highlighter.prototype.GetKeywordsCSS = function(str) {
//var str = '\\b' + str.replace(/ /g, '(?=:)\\b|\\b') + '\:\\b';
var str = '\\b([a-z_]|)' + str.replace(/ /g, '(?=:)\\b|\\b([a-z_\\*]|\\*|)') + '(?=:)\\b';
//console.log(str);
return str;
}
dp.sh.Highlighter.prototype.GetValuesCSS = function(str) {
var str = '\\b' + str.replace(/ /g, '(?!-)(?!:)\\b|\\b()') + '\:\\b';
//console.log(str);
return str;
}
dp.sh.Brushes.CSS.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.CSS.Aliases = ['css'];

View File

@@ -0,0 +1,56 @@
if (YUI && yuiConfig) {
YUI(yuiConfig).use('node', 'event-mouseenter', 'later', function(Y) {
var items = Y.all('.yui-syntax-highlight'),
openWindow = function(node, print) {
var n = Y.one('#' + node.get('id') + '-plain'),
code = n.get('value'), win = null,
h = n.get('offsetHeight');
code = code.replace(/</g, '&lt;').replace(/>/g, '&gt;');
win = window.open('', "codeview", "status=0,scrollbars=1,width=600,height=400,menubar=0,toolbar=0,directories=0");
win.document.body.innerHTML = '<pre>' + code + '</pre>';
if (print) {
Y.later(1000, win, function() {
win.focus();
win.print();
win.focus();
});
}
},
handleClick = function(e) {
if (e.target.get('tagName').toLowerCase() == 'a') {
var type = e.target.get('innerHTML').replace(/ /g, '');
switch (type) {
case 'print':
openWindow(e.target.get('parentNode.parentNode'), true);
break;
case 'viewplain':
openWindow(e.target.get('parentNode.parentNode'));
break;
case 'togglelinenumbers':
e.target.get('parentNode.parentNode').toggleClass('yui-syntax-highlight-linenumbers');
break;
case 'copy':
break;
}
}
e.halt();
};
items.each(function(i) {
//var header = Y.Node.create('<div class="syn-header hidden"><a href="#">view plain</a> | <a href="#">print</a> | <a href="#">copy</a></div>');
var header = Y.Node.create('<div class="syn-header hidden"><a href="#">view plain</a> | <a href="#">print</a> | <a href="#">toggle line numbers</a></div>');
header.on('click', handleClick);
i.insertBefore(header, i.get('firstChild'));
i.on('mouseenter', function() {
header.removeClass('hidden');
});
i.on('mouseleave', function() {
header.addClass('hidden');
});
});
});
}

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("anim-base",function(B){var C="running",N="startTime",L="elapsedTime",J="start",I="tween",M="end",D="node",K="paused",P="reverse",H="iterationCount",A=Number;var F={},O={},E;B.Anim=function(){B.Anim.superclass.constructor.apply(this,arguments);O[B.stamp(this)]=this;};B.Anim.NAME="anim";B.Anim.RE_DEFAULT_UNIT=/^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i;B.Anim.DEFAULT_UNIT="px";B.Anim.DEFAULT_EASING=function(R,Q,T,S){return T*R/S+Q;};B.Anim.behaviors={left:{get:function(R,Q){return R._getOffset(Q);}}};B.Anim.behaviors.top=B.Anim.behaviors.left;B.Anim.DEFAULT_SETTER=function(U,R,X,W,Q,V,S,T){T=T||"";U._node.setStyle(R,S(Q,A(X),A(W)-A(X),V)+T);};B.Anim.DEFAULT_GETTER=function(Q,R){return Q._node.getComputedStyle(R);};B.Anim.ATTRS={node:{setter:function(Q){Q=B.get(Q);this._node=Q;if(!Q){}return Q;}},duration:{value:1},easing:{value:B.Anim.DEFAULT_EASING,setter:function(Q){if(typeof Q==="string"&&B.Easing){return B.Easing[Q];}}},from:{},to:{},startTime:{value:0,readOnly:true},elapsedTime:{value:0,readOnly:true},running:{getter:function(){return !!F[B.stamp(this)];},value:false,readOnly:true},iterations:{value:1},iterationCount:{value:0,readOnly:true},direction:{value:"normal"},paused:{readOnly:true,value:false},reverse:{value:false}};B.Anim.run=function(){for(var Q in O){if(O[Q].run){O[Q].run();}}};B.Anim.pause=function(){for(var Q in F){if(F[Q].pause){F[Q].pause();}}B.Anim._stopTimer();};B.Anim.stop=function(){for(var Q in F){if(F[Q].stop){F[Q].stop();}}B.Anim._stopTimer();};B.Anim._startTimer=function(){if(!E){E=setInterval(B.Anim._runFrame,1);}};B.Anim._stopTimer=function(){clearInterval(E);E=0;};B.Anim._runFrame=function(){var Q=true;for(var R in F){if(F[R]._runFrame){Q=false;F[R]._runFrame();}}if(Q){B.Anim._stopTimer();}};B.Anim.RE_UNITS=/^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/;var G={run:function(){if(!this.get(C)){this._start();}else{if(this.get(K)){this._resume();}}return this;},pause:function(){if(this.get(C)){this._pause();}return this;},stop:function(Q){if(this.get(C)||this.get(K)){this._end(Q);}return this;},_added:false,_start:function(){this._set(N,new Date()-this.get(L));this._actualFrames=0;if(!this.get(K)){this._initAnimAttr();}F[B.stamp(this)]=this;B.Anim._startTimer();this.fire(J);},_pause:function(){this._set(N,null);this._set(K,true);delete F[B.stamp(this)];this.fire("pause");},_resume:function(){this._set(K,false);F[B.stamp(this)]=this;this.fire("resume");},_end:function(Q){this._set(N,null);this._set(L,0);this._set(K,false);delete F[B.stamp(this)];this.fire(M,{elapsed:this.get(L)});},_runFrame:function(){var X=this._runtimeAttr,S=B.Anim.behaviors,Y=X.easing,Z=X.duration,a=new Date()-this.get(N),W=this.get(P),U=(a>=Z),Q=Z,R,T;if(W){a=Z-a;U=(a<=0);Q=0;}for(var V in X){if(X[V].to){R=X[V];T=(V in S&&"set" in S[V])?S[V].set:B.Anim.DEFAULT_SETTER;if(!U){T(this,V,R.from,R.to,a,Z,Y,R.unit);}else{T(this,V,R.from,R.to,Q,Z,Y,R.unit);}}}this._actualFrames+=1;this._set(L,a);this.fire(I);if(U){this._lastFrame();}},_lastFrame:function(){var Q=this.get("iterations"),R=this.get(H);R+=1;if(Q==="infinite"||R<Q){if(this.get("direction")==="alternate"){this.set(P,!this.get(P));}this.fire("iteration");}else{R=0;this._end();}this._set(N,new Date());this._set(H,R);},_initAnimAttr:function(){var X=this.get("from")||{},Y=this.get("to")||{},Q=this.get("duration")*1000,T=this.get(D),W=this.get("easing")||{},V={},R=B.Anim.behaviors,Z,S,U;B.each(Y,function(d,b){if(typeof d==="function"){d=d.call(this,T);}S=X[b];if(S===undefined){S=(b in R&&"get" in R[b])?R[b].get(this,b):B.Anim.DEFAULT_GETTER(this,b);}else{if(typeof S==="function"){S=S.call(this,T);}}var a=B.Anim.RE_UNITS.exec(S);var c=B.Anim.RE_UNITS.exec(d);S=a?a[1]:S;U=c?c[1]:d;Z=c?c[2]:a?a[2]:"";if(!Z&&B.Anim.RE_DEFAULT_UNIT.test(b)){Z=B.Anim.DEFAULT_UNIT;}if(!S||!U){B.error('invalid "from" or "to" for "'+b+'"',"Anim");return;}V[b]={from:S,to:U,unit:Z};V.duration=Q;V.easing=W;},this);this._runtimeAttr=V;},_getOffset:function(R){var T=this._node,U=T.getComputedStyle(R),S=(R==="left")?"getX":"getY",V=(R==="left")?"setX":"setY";if(U==="auto"){var Q=T.getStyle("position");if(Q==="absolute"||Q==="fixed"){U=T[S]();T[V](U);}else{U=0;}}return U;}};B.extend(B.Anim,B.Base,G);},"3.0.0",{requires:["base-base","node-style"]});

View File

@@ -0,0 +1,602 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('anim-base', function(Y) {
/**
* The Animation Utility provides an API for creating advanced transitions.
* @module anim
*/
/**
* Provides the base Anim class, for animating numeric properties.
*
* @module anim
* @submodule anim-base
*/
/**
* A class for constructing animation instances.
* @class Anim
* @for Anim
* @constructor
* @extends Base
*/
var RUNNING = 'running',
START_TIME = 'startTime',
ELAPSED_TIME = 'elapsedTime',
/**
* @for Anim
* @event start
* @description fires when an animation begins.
* @param {Event} ev The start event.
* @type Event.Custom
*/
START = 'start',
/**
* @event tween
* @description fires every frame of the animation.
* @param {Event} ev The tween event.
* @type Event.Custom
*/
TWEEN = 'tween',
/**
* @event end
* @description fires after the animation completes.
* @param {Event} ev The end event.
* @type Event.Custom
*/
END = 'end',
NODE = 'node',
PAUSED = 'paused',
REVERSE = 'reverse', // TODO: cleanup
ITERATION_COUNT = 'iterationCount',
NUM = Number;
var _running = {},
_instances = {},
_timer;
Y.Anim = function() {
Y.Anim.superclass.constructor.apply(this, arguments);
_instances[Y.stamp(this)] = this;
};
Y.Anim.NAME = 'anim';
/**
* Regex of properties that should use the default unit.
*
* @property RE_DEFAULT_UNIT
* @static
*/
Y.Anim.RE_DEFAULT_UNIT = /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i;
/**
* The default unit to use with properties that pass the RE_DEFAULT_UNIT test.
*
* @property DEFAULT_UNIT
* @static
*/
Y.Anim.DEFAULT_UNIT = 'px';
Y.Anim.DEFAULT_EASING = function (t, b, c, d) {
return c * t / d + b; // linear easing
};
/**
* Bucket for custom getters and setters
*
* @property behaviors
* @static
*/
Y.Anim.behaviors = {
left: {
get: function(anim, attr) {
return anim._getOffset(attr);
}
}
};
Y.Anim.behaviors.top = Y.Anim.behaviors.left;
/**
* The default setter to use when setting object properties.
*
* @property DEFAULT_SETTER
* @static
*/
Y.Anim.DEFAULT_SETTER = function(anim, att, from, to, elapsed, duration, fn, unit) {
unit = unit || '';
anim._node.setStyle(att, fn(elapsed, NUM(from), NUM(to) - NUM(from), duration) + unit);
};
/**
* The default getter to use when getting object properties.
*
* @property DEFAULT_GETTER
* @static
*/
Y.Anim.DEFAULT_GETTER = function(anim, prop) {
return anim._node.getComputedStyle(prop);
};
Y.Anim.ATTRS = {
/**
* The object to be animated.
* @attribute node
* @type Node
*/
node: {
setter: function(node) {
node = Y.get(node);
this._node = node;
if (!node) {
}
return node;
}
},
/**
* The length of the animation. Defaults to "1" (second).
* @attribute duration
* @type NUM
*/
duration: {
value: 1
},
/**
* The method that will provide values to the attribute(s) during the animation.
* Defaults to "Easing.easeNone".
* @attribute easing
* @type Function
*/
easing: {
value: Y.Anim.DEFAULT_EASING,
setter: function(val) {
if (typeof val === 'string' && Y.Easing) {
return Y.Easing[val];
}
}
},
/**
* The starting values for the animated properties.
* Fields may be strings, numbers, or functions.
* If a function is used, the return value becomes the from value.
* If no from value is specified, the DEFAULT_GETTER will be used.
* @attribute from
* @type Object
*/
from: {},
/**
* The ending values for the animated properties.
* Fields may be strings, numbers, or functions.
* @attribute to
* @type Object
*/
to: {},
/**
* Date stamp for the first frame of the animation.
* @attribute startTime
* @type Int
* @default 0
* @readOnly
*/
startTime: {
value: 0,
readOnly: true
},
/**
* Current time the animation has been running.
* @attribute elapsedTime
* @type Int
* @default 0
* @readOnly
*/
elapsedTime: {
value: 0,
readOnly: true
},
/**
* Whether or not the animation is currently running.
* @attribute running
* @type Boolean
* @default false
* @readOnly
*/
running: {
getter: function() {
return !!_running[Y.stamp(this)];
},
value: false,
readOnly: true
},
/**
* The number of times the animation should run
* @attribute iterations
* @type Int
* @default 1
*/
iterations: {
value: 1
},
/**
* The number of iterations that have occurred.
* Resets when an animation ends (reaches iteration count or stop() called).
* @attribute iterationCount
* @type Int
* @default 0
* @readOnly
*/
iterationCount: {
value: 0,
readOnly: true
},
/**
* How iterations of the animation should behave.
* Possible values are "normal" and "alternate".
* Normal will repeat the animation, alternate will reverse on every other pass.
*
* @attribute direction
* @type String
* @default "normal"
*/
direction: {
value: 'normal' // | alternate (fwd on odd, rev on even per spec)
},
/**
* Whether or not the animation is currently paused.
* @attribute paused
* @type Boolean
* @default false
* @readOnly
*/
paused: {
readOnly: true,
value: false
},
/**
* If true, animation begins from last frame
* @attribute reverse
* @type Boolean
* @default false
*/
reverse: {
value: false
}
};
/**
* Runs all animation instances.
* @method run
* @static
*/
Y.Anim.run = function() {
for (var i in _instances) {
if (_instances[i].run) {
_instances[i].run();
}
}
};
/**
* Pauses all animation instances.
* @method pause
* @static
*/
Y.Anim.pause = function() {
for (var i in _running) { // stop timer if nothing running
if (_running[i].pause) {
_running[i].pause();
}
}
Y.Anim._stopTimer();
};
/**
* Stops all animation instances.
* @method stop
* @static
*/
Y.Anim.stop = function() {
for (var i in _running) { // stop timer if nothing running
if (_running[i].stop) {
_running[i].stop();
}
}
Y.Anim._stopTimer();
};
Y.Anim._startTimer = function() {
if (!_timer) {
_timer = setInterval(Y.Anim._runFrame, 1);
}
};
Y.Anim._stopTimer = function() {
clearInterval(_timer);
_timer = 0;
};
/**
* Called per Interval to handle each animation frame.
* @method _runFrame
* @private
* @static
*/
Y.Anim._runFrame = function() {
var done = true;
for (var anim in _running) {
if (_running[anim]._runFrame) {
done = false;
_running[anim]._runFrame();
}
}
if (done) {
Y.Anim._stopTimer();
}
};
Y.Anim.RE_UNITS = /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/;
var proto = {
/**
* Starts or resumes an animation.
* percent start time marker.
* @method run
* @chainable
*/
run: function() {
if (!this.get(RUNNING)) {
this._start();
} else if (this.get(PAUSED)) {
this._resume();
}
return this;
},
/**
* Pauses the animation and
* freezes it in its current state and time.
* Calling run() will continue where it left off.
* @method pause
* @chainable
*/
pause: function() {
if (this.get(RUNNING)) {
this._pause();
}
return this;
},
/**
* Stops the animation and resets its time.
* @method stop
* @chainable
*/
stop: function(finish) {
if (this.get(RUNNING) || this.get(PAUSED)) {
this._end(finish);
}
return this;
},
_added: false,
_start: function() {
this._set(START_TIME, new Date() - this.get(ELAPSED_TIME));
this._actualFrames = 0;
if (!this.get(PAUSED)) {
this._initAnimAttr();
}
_running[Y.stamp(this)] = this;
Y.Anim._startTimer();
this.fire(START);
},
_pause: function() {
this._set(START_TIME, null);
this._set(PAUSED, true);
delete _running[Y.stamp(this)];
/**
* @event pause
* @description fires when an animation is paused.
* @param {Event} ev The pause event.
* @type Event.Custom
*/
this.fire('pause');
},
_resume: function() {
this._set(PAUSED, false);
_running[Y.stamp(this)] = this;
/**
* @event resume
* @description fires when an animation is resumed (run from pause).
* @param {Event} ev The pause event.
* @type Event.Custom
*/
this.fire('resume');
},
_end: function(finish) {
this._set(START_TIME, null);
this._set(ELAPSED_TIME, 0);
this._set(PAUSED, false);
delete _running[Y.stamp(this)];
this.fire(END, {elapsed: this.get(ELAPSED_TIME)});
},
_runFrame: function() {
var attr = this._runtimeAttr,
customAttr = Y.Anim.behaviors,
easing = attr.easing,
d = attr.duration,
t = new Date() - this.get(START_TIME),
reversed = this.get(REVERSE),
done = (t >= d),
lastFrame = d,
attribute,
setter;
if (reversed) {
t = d - t;
done = (t <= 0);
lastFrame = 0;
}
for (var i in attr) {
if (attr[i].to) {
attribute = attr[i];
setter = (i in customAttr && 'set' in customAttr[i]) ?
customAttr[i].set : Y.Anim.DEFAULT_SETTER;
if (!done) {
setter(this, i, attribute.from, attribute.to, t, d, easing, attribute.unit);
} else { // ensure final frame value is set
// TODO: handle keyframes
setter(this, i, attribute.from, attribute.to, lastFrame, d, easing, attribute.unit);
}
}
}
this._actualFrames += 1;
this._set(ELAPSED_TIME, t);
this.fire(TWEEN);
if (done) {
this._lastFrame();
}
},
_lastFrame: function() {
var iter = this.get('iterations'),
iterCount = this.get(ITERATION_COUNT);
iterCount += 1;
if (iter === 'infinite' || iterCount < iter) {
if (this.get('direction') === 'alternate') {
this.set(REVERSE, !this.get(REVERSE)); // flip it
}
/**
* @event iteration
* @description fires when an animation begins an iteration.
* @param {Event} ev The iteration event.
* @type Event.Custom
*/
this.fire('iteration');
} else {
iterCount = 0;
this._end();
}
this._set(START_TIME, new Date());
this._set(ITERATION_COUNT, iterCount);
},
_initAnimAttr: function() {
var from = this.get('from') || {},
to = this.get('to') || {},
dur = this.get('duration') * 1000,
node = this.get(NODE),
easing = this.get('easing') || {},
attr = {},
customAttr = Y.Anim.behaviors,
unit, begin, end;
Y.each(to, function(val, name) {
if (typeof val === 'function') {
val = val.call(this, node);
}
begin = from[name];
if (begin === undefined) {
begin = (name in customAttr && 'get' in customAttr[name]) ?
customAttr[name].get(this, name) : Y.Anim.DEFAULT_GETTER(this, name);
} else if (typeof begin === 'function') {
begin = begin.call(this, node);
}
var mFrom = Y.Anim.RE_UNITS.exec(begin);
var mTo = Y.Anim.RE_UNITS.exec(val);
begin = mFrom ? mFrom[1] : begin;
end = mTo ? mTo[1] : val;
unit = mTo ? mTo[2] : mFrom ? mFrom[2] : ''; // one might be zero TODO: mixed units
if (!unit && Y.Anim.RE_DEFAULT_UNIT.test(name)) {
unit = Y.Anim.DEFAULT_UNIT;
}
if (!begin || !end) {
Y.error('invalid "from" or "to" for "' + name + '"', 'Anim');
return;
}
attr[name] = {
from: begin,
to: end,
unit: unit
};
attr.duration = dur;
attr.easing = easing;
}, this);
this._runtimeAttr = attr;
},
// TODO: move to computedStyle? (browsers dont agree on default computed offsets)
_getOffset: function(attr) {
var node = this._node,
val = node.getComputedStyle(attr),
get = (attr === 'left') ? 'getX': 'getY',
set = (attr === 'left') ? 'setX': 'setY';
if (val === 'auto') {
var position = node.getStyle('position');
if (position === 'absolute' || position === 'fixed') {
val = node[get]();
node[set](val);
} else {
val = 0;
}
}
return val;
}
};
Y.extend(Y.Anim, Y.Base, proto);
}, '3.0.0' ,{requires:['base-base', 'node-style']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("anim-color",function(B){var A=Number;B.Anim.behaviors.color={set:function(F,D,I,H,C,G,E){I=B.Color.re_RGB.exec(B.Color.toRGB(I));H=B.Color.re_RGB.exec(B.Color.toRGB(H));if(!I||I.length<3||!H||H.length<3){B.error("invalid from or to passed to color behavior");}F._node.setStyle(D,"rgb("+[Math.floor(E(C,A(I[1]),A(H[1])-A(I[1]),G)),Math.floor(E(C,A(I[2]),A(H[2])-A(I[2]),G)),Math.floor(E(C,A(I[3]),A(H[3])-A(I[3]),G))].join(", ")+")");},get:function(D,C){var E=D._node.getComputedStyle(C);E=(E==="transparent")?"rgb(255, 255, 255)":E;return E;}};B.each(["backgroundColor","borderColor","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"],function(C,D){B.Anim.behaviors[C]=B.Anim.behaviors.color;});},"3.0.0",{requires:["anim-base"]});

View File

@@ -0,0 +1,55 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('anim-color', function(Y) {
/**
* Adds support for color properties in <code>to</code>
* and <code>from</code> attributes.
* @module anim
* @submodule anim-color
*/
var NUM = Number;
Y.Anim.behaviors.color = {
set: function(anim, att, from, to, elapsed, duration, fn) {
from = Y.Color.re_RGB.exec(Y.Color.toRGB(from));
to = Y.Color.re_RGB.exec(Y.Color.toRGB(to));
if (!from || from.length < 3 || !to || to.length < 3) {
Y.error('invalid from or to passed to color behavior');
}
anim._node.setStyle(att, 'rgb(' + [
Math.floor(fn(elapsed, NUM(from[1]), NUM(to[1]) - NUM(from[1]), duration)),
Math.floor(fn(elapsed, NUM(from[2]), NUM(to[2]) - NUM(from[2]), duration)),
Math.floor(fn(elapsed, NUM(from[3]), NUM(to[3]) - NUM(from[3]), duration))
].join(', ') + ')');
},
// TODO: default bgcolor const
get: function(anim, att) {
var val = anim._node.getComputedStyle(att);
val = (val === 'transparent') ? 'rgb(255, 255, 255)' : val;
return val;
}
};
Y.each(['backgroundColor',
'borderColor',
'borderTopColor',
'borderRightColor',
'borderBottomColor',
'borderLeftColor'],
function(v, i) {
Y.Anim.behaviors[v] = Y.Anim.behaviors.color;
}
);
}, '3.0.0' ,{requires:['anim-base']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("anim-curve",function(A){A.Anim.behaviors.curve={set:function(F,C,I,H,B,G,E){I=I.slice.call(I);H=H.slice.call(H);var D=E(B,0,100,G)/100;H.unshift(I);F._node.setXY(A.Anim.getBezier(H,D));},get:function(C,B){return C._node.getXY();}};A.Anim.getBezier=function(F,E){var G=F.length;var D=[];for(var C=0;C<G;++C){D[C]=[F[C][0],F[C][1]];}for(var B=1;B<G;++B){for(C=0;C<G-B;++C){D[C][0]=(1-E)*D[C][0]+E*D[parseInt(C+1,10)][0];D[C][1]=(1-E)*D[C][1]+E*D[parseInt(C+1,10)][1];}}return[D[0][0],D[0][1]];};},"3.0.0",{requires:["anim-xy"]});

View File

@@ -0,0 +1,64 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('anim-curve', function(Y) {
/**
* Adds support for the <code>curve</code> property for the <code>to</code>
* attribute. A curve is zero or more control points and an end point.
* @module anim
* @submodule anim-curve
*/
Y.Anim.behaviors.curve = {
set: function(anim, att, from, to, elapsed, duration, fn) {
from = from.slice.call(from);
to = to.slice.call(to);
var t = fn(elapsed, 0, 100, duration) / 100;
to.unshift(from);
anim._node.setXY(Y.Anim.getBezier(to, t));
},
get: function(anim, att) {
return anim._node.getXY();
}
};
/**
* Get the current position of the animated element based on t.
* Each point is an array of "x" and "y" values (0 = x, 1 = y)
* At least 2 points are required (start and end).
* First point is start. Last point is end.
* Additional control points are optional.
* @for Anim
* @method getBezier
* @static
* @param {Array} points An array containing Bezier points
* @param {Number} t A number between 0 and 1 which is the basis for determining current position
* @return {Array} An array containing int x and y member data
*/
Y.Anim.getBezier = function(points, t) {
var n = points.length;
var tmp = [];
for (var i = 0; i < n; ++i){
tmp[i] = [points[i][0], points[i][1]]; // save input
}
for (var j = 1; j < n; ++j) {
for (i = 0; i < n - j; ++i) {
tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
}
}
return [ tmp[0][0], tmp[0][1] ];
};
}, '3.0.0' ,{requires:['anim-xy']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("anim-easing",function(A){A.Easing={easeNone:function(C,B,E,D){return E*C/D+B;},easeIn:function(C,B,E,D){return E*(C/=D)*C+B;},easeOut:function(C,B,E,D){return -E*(C/=D)*(C-2)+B;},easeBoth:function(C,B,E,D){if((C/=D/2)<1){return E/2*C*C+B;}return -E/2*((--C)*(C-2)-1)+B;},easeInStrong:function(C,B,E,D){return E*(C/=D)*C*C*C+B;},easeOutStrong:function(C,B,E,D){return -E*((C=C/D-1)*C*C*C-1)+B;},easeBothStrong:function(C,B,E,D){if((C/=D/2)<1){return E/2*C*C*C*C+B;}return -E/2*((C-=2)*C*C*C-2)+B;},elasticIn:function(D,B,H,G,C,F){var E;if(D===0){return B;}if((D/=G)===1){return B+H;}if(!F){F=G*0.3;}if(!C||C<Math.abs(H)){C=H;E=F/4;}else{E=F/(2*Math.PI)*Math.asin(H/C);}return -(C*Math.pow(2,10*(D-=1))*Math.sin((D*G-E)*(2*Math.PI)/F))+B;},elasticOut:function(D,B,H,G,C,F){var E;if(D===0){return B;}if((D/=G)===1){return B+H;}if(!F){F=G*0.3;}if(!C||C<Math.abs(H)){C=H;E=F/4;}else{E=F/(2*Math.PI)*Math.asin(H/C);}return C*Math.pow(2,-10*D)*Math.sin((D*G-E)*(2*Math.PI)/F)+H+B;},elasticBoth:function(D,B,H,G,C,F){var E;if(D===0){return B;}if((D/=G/2)===2){return B+H;}if(!F){F=G*(0.3*1.5);}if(!C||C<Math.abs(H)){C=H;E=F/4;}else{E=F/(2*Math.PI)*Math.asin(H/C);}if(D<1){return -0.5*(C*Math.pow(2,10*(D-=1))*Math.sin((D*G-E)*(2*Math.PI)/F))+B;}return C*Math.pow(2,-10*(D-=1))*Math.sin((D*G-E)*(2*Math.PI)/F)*0.5+H+B;},backIn:function(C,B,F,E,D){if(D===undefined){D=1.70158;}if(C===E){C-=0.001;}return F*(C/=E)*C*((D+1)*C-D)+B;},backOut:function(C,B,F,E,D){if(typeof D==="undefined"){D=1.70158;}return F*((C=C/E-1)*C*((D+1)*C+D)+1)+B;},backBoth:function(C,B,F,E,D){if(typeof D==="undefined"){D=1.70158;}if((C/=E/2)<1){return F/2*(C*C*(((D*=(1.525))+1)*C-D))+B;}return F/2*((C-=2)*C*(((D*=(1.525))+1)*C+D)+2)+B;},bounceIn:function(C,B,E,D){return E-A.Easing.bounceOut(D-C,0,E,D)+B;},bounceOut:function(C,B,E,D){if((C/=D)<(1/2.75)){return E*(7.5625*C*C)+B;}else{if(C<(2/2.75)){return E*(7.5625*(C-=(1.5/2.75))*C+0.75)+B;}else{if(C<(2.5/2.75)){return E*(7.5625*(C-=(2.25/2.75))*C+0.9375)+B;}}}return E*(7.5625*(C-=(2.625/2.75))*C+0.984375)+B;},bounceBoth:function(C,B,E,D){if(C<D/2){return A.Easing.bounceIn(C*2,0,E,D)*0.5+B;}return A.Easing.bounceOut(C*2-D,0,E,D)*0.5+E*0.5+B;}};},"3.0.0",{requires:["anim-base"]});

View File

@@ -0,0 +1,355 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('anim-easing', function(Y) {
/*
TERMS OF USE - EASING EQUATIONS
Open source under the BSD License.
Copyright 2001 Robert Penner All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* The easing module provides methods for customizing
* how an animation behaves during each run.
* @class Easing
* @module anim
* @submodule anim-easing
*/
Y.Easing = {
/**
* Uniform speed between points.
* @for Easing
* @method easeNone
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @return {Number} The computed value for the current animation frame
*/
easeNone: function (t, b, c, d) {
return c*t/d + b;
},
/**
* Begins slowly and accelerates towards end. (quadratic)
* @method easeIn
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @return {Number} The computed value for the current animation frame
*/
easeIn: function (t, b, c, d) {
return c*(t/=d)*t + b;
},
/**
* Begins quickly and decelerates towards end. (quadratic)
* @method easeOut
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @return {Number} The computed value for the current animation frame
*/
easeOut: function (t, b, c, d) {
return -c *(t/=d)*(t-2) + b;
},
/**
* Begins slowly and decelerates towards end. (quadratic)
* @method easeBoth
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @return {Number} The computed value for the current animation frame
*/
easeBoth: function (t, b, c, d) {
if ((t/=d/2) < 1) {
return c/2*t*t + b;
}
return -c/2 * ((--t)*(t-2) - 1) + b;
},
/**
* Begins slowly and accelerates towards end. (quartic)
* @method easeInStrong
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @return {Number} The computed value for the current animation frame
*/
easeInStrong: function (t, b, c, d) {
return c*(t/=d)*t*t*t + b;
},
/**
* Begins quickly and decelerates towards end. (quartic)
* @method easeOutStrong
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @return {Number} The computed value for the current animation frame
*/
easeOutStrong: function (t, b, c, d) {
return -c * ((t=t/d-1)*t*t*t - 1) + b;
},
/**
* Begins slowly and decelerates towards end. (quartic)
* @method easeBothStrong
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @return {Number} The computed value for the current animation frame
*/
easeBothStrong: function (t, b, c, d) {
if ((t/=d/2) < 1) {
return c/2*t*t*t*t + b;
}
return -c/2 * ((t-=2)*t*t*t - 2) + b;
},
/**
* Snap in elastic effect.
* @method elasticIn
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @param {Number} a Amplitude (optional)
* @param {Number} p Period (optional)
* @return {Number} The computed value for the current animation frame
*/
elasticIn: function (t, b, c, d, a, p) {
var s;
if (t === 0) {
return b;
}
if ( (t /= d) === 1 ) {
return b+c;
}
if (!p) {
p = d* 0.3;
}
if (!a || a < Math.abs(c)) {
a = c;
s = p/4;
}
else {
s = p/(2*Math.PI) * Math.asin (c/a);
}
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
},
/**
* Snap out elastic effect.
* @method elasticOut
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @param {Number} a Amplitude (optional)
* @param {Number} p Period (optional)
* @return {Number} The computed value for the current animation frame
*/
elasticOut: function (t, b, c, d, a, p) {
var s;
if (t === 0) {
return b;
}
if ( (t /= d) === 1 ) {
return b+c;
}
if (!p) {
p=d * 0.3;
}
if (!a || a < Math.abs(c)) {
a = c;
s = p / 4;
}
else {
s = p/(2*Math.PI) * Math.asin (c/a);
}
return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
},
/**
* Snap both elastic effect.
* @method elasticBoth
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @param {Number} a Amplitude (optional)
* @param {Number} p Period (optional)
* @return {Number} The computed value for the current animation frame
*/
elasticBoth: function (t, b, c, d, a, p) {
var s;
if (t === 0) {
return b;
}
if ( (t /= d/2) === 2 ) {
return b+c;
}
if (!p) {
p = d*(0.3*1.5);
}
if ( !a || a < Math.abs(c) ) {
a = c;
s = p/4;
}
else {
s = p/(2*Math.PI) * Math.asin (c/a);
}
if (t < 1) {
return -0.5*(a*Math.pow(2,10*(t-=1)) *
Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
}
return a*Math.pow(2,-10*(t-=1)) *
Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b;
},
/**
* Backtracks slightly, then reverses direction and moves to end.
* @method backIn
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @param {Number} s Overshoot (optional)
* @return {Number} The computed value for the current animation frame
*/
backIn: function (t, b, c, d, s) {
if (s === undefined) {
s = 1.70158;
}
if (t === d) {
t -= 0.001;
}
return c*(t/=d)*t*((s+1)*t - s) + b;
},
/**
* Overshoots end, then reverses and comes back to end.
* @method backOut
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @param {Number} s Overshoot (optional)
* @return {Number} The computed value for the current animation frame
*/
backOut: function (t, b, c, d, s) {
if (typeof s === 'undefined') {
s = 1.70158;
}
return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
},
/**
* Backtracks slightly, then reverses direction, overshoots end,
* then reverses and comes back to end.
* @method backBoth
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @param {Number} s Overshoot (optional)
* @return {Number} The computed value for the current animation frame
*/
backBoth: function (t, b, c, d, s) {
if (typeof s === 'undefined') {
s = 1.70158;
}
if ((t /= d/2 ) < 1) {
return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
}
return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
},
/**
* Bounce off of start.
* @method bounceIn
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @return {Number} The computed value for the current animation frame
*/
bounceIn: function (t, b, c, d) {
return c - Y.Easing.bounceOut(d-t, 0, c, d) + b;
},
/**
* Bounces off end.
* @method bounceOut
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @return {Number} The computed value for the current animation frame
*/
bounceOut: function (t, b, c, d) {
if ((t/=d) < (1/2.75)) {
return c*(7.5625*t*t) + b;
} else if (t < (2/2.75)) {
return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b;
} else if (t < (2.5/2.75)) {
return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b;
}
return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b;
},
/**
* Bounces off start and end.
* @method bounceBoth
* @param {Number} t Time value used to compute current value
* @param {Number} b Starting value
* @param {Number} c Delta between start and end values
* @param {Number} d Total length of animation
* @return {Number} The computed value for the current animation frame
*/
bounceBoth: function (t, b, c, d) {
if (t < d/2) {
return Y.Easing.bounceIn(t * 2, 0, c, d) * 0.5 + b;
}
return Y.Easing.bounceOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
}
};
}, '3.0.0' ,{requires:['anim-base']});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("anim-node-plugin",function(B){var A=function(C){C=(C)?B.merge(C):{};C.node=C.host;A.superclass.constructor.apply(this,arguments);};A.NAME="nodefx";A.NS="fx";B.extend(A,B.Anim);B.namespace("Plugin");B.Plugin.NodeFX=A;},"3.0.0",{requires:["node-pluginhost","anim-base"]});

View File

@@ -0,0 +1,33 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('anim-node-plugin', function(Y) {
/**
* Binds an Anim instance to a Node instance
* @module anim
* @class Plugin.NodeFX
* @extends Base
* @submodule anim-node-plugin
*/
var NodeFX = function(config) {
config = (config) ? Y.merge(config) : {};
config.node = config.host;
NodeFX.superclass.constructor.apply(this, arguments);
};
NodeFX.NAME = "nodefx";
NodeFX.NS = "fx";
Y.extend(NodeFX, Y.Anim);
Y.namespace('Plugin');
Y.Plugin.NodeFX = NodeFX;
}, '3.0.0' ,{requires:['node-pluginhost', 'anim-base']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("anim-scroll",function(B){var A=Number;B.Anim.behaviors.scroll={set:function(F,G,I,J,K,E,H){var D=F._node,C=([H(K,A(I[0]),A(J[0])-A(I[0]),E),H(K,A(I[1]),A(J[1])-A(I[1]),E)]);if(C[0]){D.set("scrollLeft",C[0]);}if(C[1]){D.set("scrollTop",C[1]);}},get:function(D){var C=D._node;return[C.get("scrollLeft"),C.get("scrollTop")];}};},"3.0.0",{requires:["anim-base"]});

View File

@@ -0,0 +1,45 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('anim-scroll', function(Y) {
/**
* Adds support for the <code>scroll</code> property in <code>to</code>
* and <code>from</code> attributes.
* @module anim
* @submodule anim-scroll
*/
var NUM = Number;
//TODO: deprecate for scrollTop/Left properties?
Y.Anim.behaviors.scroll = {
set: function(anim, att, from, to, elapsed, duration, fn) {
var
node = anim._node,
val = ([
fn(elapsed, NUM(from[0]), NUM(to[0]) - NUM(from[0]), duration),
fn(elapsed, NUM(from[1]), NUM(to[1]) - NUM(from[1]), duration)
]);
if (val[0]) {
node.set('scrollLeft', val[0]);
}
if (val[1]) {
node.set('scrollTop', val[1]);
}
},
get: function(anim) {
var node = anim._node;
return [node.get('scrollLeft'), node.get('scrollTop')];
}
};
}, '3.0.0' ,{requires:['anim-base']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("anim-xy",function(B){var A=Number;B.Anim.behaviors.xy={set:function(F,D,I,H,C,G,E){F._node.setXY([E(C,A(I[0]),A(H[0])-A(I[0]),G),E(C,A(I[1]),A(H[1])-A(I[1]),G)]);},get:function(C){return C._node.getXY();}};},"3.0.0",{requires:["anim-base","node-screen"]});

View File

@@ -0,0 +1,33 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('anim-xy', function(Y) {
/**
* Adds support for the <code>xy</code> property in <code>from</code> and
* <code>to</code> attributes.
* @module anim
* @submodule anim-xy
*/
var NUM = Number;
Y.Anim.behaviors.xy = {
set: function(anim, att, from, to, elapsed, duration, fn) {
anim._node.setXY([
fn(elapsed, NUM(from[0]), NUM(to[0]) - NUM(from[0]), duration),
fn(elapsed, NUM(from[1]), NUM(to[1]) - NUM(from[1]), duration)
]);
},
get: function(anim) {
return anim._node.getXY();
}
};
}, '3.0.0' ,{requires:['anim-base', 'node-screen']});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("async-queue",function(G){G.AsyncQueue=function(){this._init();this.add.apply(this,arguments);};var E=G.AsyncQueue,C="execute",B="shift",D="promote",H="remove",A=G.Lang.isObject,F=G.Lang.isFunction;E.defaults=G.mix({autoContinue:true,iterations:1,timeout:10,until:function(){this.iterations|=0;return this.iterations<=0;}},G.config.queueDefaults||{});G.extend(E,G.EventTarget,{_running:false,_init:function(){G.EventTarget.call(this,{emitFacade:true});this._q=[];this.defaults={};this._initEvents();},_initEvents:function(){this.publish("execute",{defaultFn:this._defExecFn,emitFacade:true});this.publish("shift",{defaultFn:this._defShiftFn,emitFacade:true});this.publish("add",{defaultFn:this._defAddFn,emitFacade:true});this.publish("promote",{defaultFn:this._defPromoteFn,emitFacade:true});this.publish("remove",{defaultFn:this._defRemoveFn,emitFacade:true});},next:function(){var I;while(this._q.length){I=this._q[0]=this._prepare(this._q[0]);if(I&&I.until()){this.fire(B,{callback:I});I=null;}else{break;}}return I||null;},_defShiftFn:function(I){if(this.indexOf(I.callback)===0){this._q.shift();}},_prepare:function(K){if(F(K)&&K._prepared){return K;}var I=G.merge(E.defaults,{context:this,args:[],_prepared:true},this.defaults,(F(K)?{fn:K}:K)),J=G.bind(function(){if(!J._running){J.iterations--;}if(F(J.fn)){J.fn.apply(J.context||G,G.Array(J.args));}},this);return G.mix(J,I);},run:function(){var J,I=true;for(J=this.next();I&&J&&!this.isRunning();J=this.next()){I=(J.timeout<0)?this._execute(J):this._schedule(J);}if(!J){this.fire("complete");}return this;},_execute:function(J){this._running=J._running=true;J.iterations--;this.fire(C,{callback:J});var I=this._running&&J.autoContinue;this._running=J._running=false;return I;},_schedule:function(I){this._running=G.later(I.timeout,this,function(){if(this._execute(I)){this.run();}});return false;},isRunning:function(){return !!this._running;},_defExecFn:function(I){I.callback();},add:function(){this.fire("add",{callbacks:G.Array(arguments,0,true)});return this;},_defAddFn:function(J){var K=this._q,I=[];G.Array.each(J.callbacks,function(L){if(A(L)){K.push(L);I.push(L);}});J.added=I;},pause:function(){if(A(this._running)){this._running.cancel();}this._running=false;return this;},stop:function(){this._q=[];return this.pause();},indexOf:function(L){var J=0,I=this._q.length,K;for(;J<I;++J){K=this._q[J];if(K===L||K.id===L){return J;}}return -1;},getCallback:function(J){var I=this.indexOf(J);return(I>-1)?this._q[I]:null;},promote:function(K){var J={callback:K},I;if(this.isRunning()){I=this.after(B,function(){this.fire(D,J);I.detach();},this);}else{this.fire(D,J);}return this;},_defPromoteFn:function(K){var I=this.indexOf(K.callback),J=(I>-1)?this._q.splice(I,1)[0]:null;K.promoted=J;if(J){this._q.unshift(J);}},remove:function(K){var J={callback:K},I;if(this.isRunning()){I=this.after(B,function(){this.fire(H,J);I.detach();},this);}else{this.fire(H,J);}return this;},_defRemoveFn:function(J){var I=this.indexOf(J.callback);J.removed=(I>-1)?this._q.splice(I,1)[0]:null;},size:function(){if(!this.isRunning()){this.next();}return this._q.length;}});},"3.0.0",{requires:["event-custom"]});

View File

@@ -0,0 +1,536 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('async-queue', function(Y) {
/**
* <p>AsyncQueue allows you create a chain of function callbacks executed
* via setTimeout (or synchronously) that are guaranteed to run in order.
* Items in the queue can be promoted or removed. Start or resume the
* execution chain with run(). pause() to temporarily delay execution, or
* stop() to halt and clear the queue.</p>
*
* @module async-queue
*/
/**
* <p>A specialized queue class that supports scheduling callbacks to execute
* sequentially, iteratively, even asynchronously.</p>
*
* <p>Callbacks can be function refs or objects with the following keys. Only
* the <code>fn</code> key is required.</p>
*
* <ul>
* <li><code>fn</code> -- The callback function</li>
* <li><code>context</code> -- The execution context for the callbackFn.</li>
* <li><code>args</code> -- Arguments to pass to callbackFn.</li>
* <li><code>timeout</code> -- Millisecond delay before executing callbackFn.
* (Applies to each iterative execution of callback)</li>
* <li><code>iterations</code> -- Number of times to repeat the callback.
* <li><code>until</code> -- Repeat the callback until this function returns
* true. This setting trumps iterations.</li>
* <li><code>autoContinue</code> -- Set to false to prevent the AsyncQueue from
* executing the next callback in the Queue after
* the callback completes.</li>
* <li><code>id</code> -- Name that can be used to get, promote, get the
* indexOf, or delete this callback.</li>
* </ul>
*
* @class AsyncQueue
* @extends EventTarget
* @constructor
* @param callback* {Function|Object} 0..n callbacks to seed the queue
*/
Y.AsyncQueue = function() {
this._init();
this.add.apply(this, arguments);
};
var Queue = Y.AsyncQueue,
EXECUTE = 'execute',
SHIFT = 'shift',
PROMOTE = 'promote',
REMOVE = 'remove',
isObject = Y.Lang.isObject,
isFunction = Y.Lang.isFunction;
/**
* <p>Static default values used to populate callback configuration properties.
* Preconfigured defaults include:</p>
*
* <ul>
* <li><code>autoContinue</code>: <code>true</code></li>
* <li><code>iterations</code>: 1</li>
* <li><code>timeout</code>: 10 (10ms between callbacks)</li>
* <li><code>until</code>: (function to run until iterations &lt;= 0)</li>
* </ul>
*
* @property AsyncQueue.defaults
* @type {Object}
* @static
*/
Queue.defaults = Y.mix({
autoContinue : true,
iterations : 1,
timeout : 10,
until : function () {
this.iterations |= 0;
return this.iterations <= 0;
}
}, Y.config.queueDefaults || {});
Y.extend(Queue, Y.EventTarget, {
/**
* Used to indicate the queue is currently executing a callback.
*
* @property _running
* @type {Boolean|Object} true for synchronous callback execution, the
* return handle from Y.later for async callbacks.
* Otherwise false.
* @protected
*/
_running : false,
/**
* Initializes the AsyncQueue instance properties and events.
*
* @method _init
* @protected
*/
_init : function () {
Y.EventTarget.call(this, { emitFacade: true });
this._q = [];
/**
* Callback defaults for this instance. Static defaults that are not
* overridden are also included.
*
* @property defaults
* @type {Object}
*/
this.defaults = {};
this._initEvents();
},
/**
* Initializes the instance events.
*
* @method _initEvents
* @protected
*/
_initEvents : function () {
/*
this.publish({
'execute' : { defaultFn : this._defExecFn },
'shift' : { defaultFn : this._defShiftFn },
'add' : { defaultFn : this._defAddFn },
'promote' : { defaultFn : this._defPromoteFn },
'remove' : { defaultFn : this._defRemoveFn }
});
*/
this.publish('execute' , { defaultFn : this._defExecFn, emitFacade: true });
this.publish('shift' , { defaultFn : this._defShiftFn, emitFacade: true });
this.publish('add' , { defaultFn : this._defAddFn, emitFacade: true });
this.publish('promote' , { defaultFn : this._defPromoteFn, emitFacade: true });
this.publish('remove' , { defaultFn : this._defRemoveFn, emitFacade: true });
},
/**
* Returns the next callback needing execution. If a callback is
* configured to repeat via iterations or until, it will be returned until
* the completion criteria is met.
*
* When the queue is empty, null is returned.
*
* @method next
* @return {Function} the callback to execute
*/
next : function () {
var callback;
while (this._q.length) {
callback = this._q[0] = this._prepare(this._q[0]);
if (callback && callback.until()) {
this.fire(SHIFT, { callback: callback });
callback = null;
} else {
break;
}
}
return callback || null;
},
/**
* Default functionality for the &quot;shift&quot; event. Shifts the
* callback stored in the event object's <em>callback</em> property from
* the queue if it is the first item.
*
* @method _defShiftFn
* @param e {Event} The event object
* @protected
*/
_defShiftFn : function (e) {
if (this.indexOf(e.callback) === 0) {
this._q.shift();
}
},
/**
* Creates a wrapper function to execute the callback using the aggregated
* configuration generated by combining the static AsyncQueue.defaults, the
* instance defaults, and the specified callback settings.
*
* The wrapper function is decorated with the callback configuration as
* properties for runtime modification.
*
* @method _prepare
* @param callback {Object|Function} the raw callback
* @return {Function} a decorated function wrapper to execute the callback
* @protected
*/
_prepare: function (callback) {
if (isFunction(callback) && callback._prepared) {
return callback;
}
var config = Y.merge(
Queue.defaults,
{ context : this, args: [], _prepared: true },
this.defaults,
(isFunction(callback) ? { fn: callback } : callback)),
wrapper = Y.bind(function () {
if (!wrapper._running) {
wrapper.iterations--;
}
if (isFunction(wrapper.fn)) {
wrapper.fn.apply(wrapper.context || Y,
Y.Array(wrapper.args));
}
}, this);
return Y.mix(wrapper, config);
},
/**
* Sets the queue in motion. All queued callbacks will be executed in
* order unless pause() or stop() is called or if one of the callbacks is
* configured with autoContinue: false.
*
* @method run
* @return {AsyncQueue} the AsyncQueue instance
* @chainable
*/
run : function () {
var callback,
cont = true;
for (callback = this.next();
cont && callback && !this.isRunning();
callback = this.next())
{
cont = (callback.timeout < 0) ?
this._execute(callback) :
this._schedule(callback);
}
if (!callback) {
/**
* Event fired after the last queued callback is executed.
* @event complete
*/
this.fire('complete');
}
return this;
},
/**
* Handles the execution of callbacks. Returns a boolean indicating
* whether it is appropriate to continue running.
*
* @method _execute
* @param callback {Object} the callback object to execute
* @return {Boolean} whether the run loop should continue
* @protected
*/
_execute : function (callback) {
this._running = callback._running = true;
callback.iterations--;
this.fire(EXECUTE, { callback: callback });
var cont = this._running && callback.autoContinue;
this._running = callback._running = false;
return cont;
},
/**
* Schedules the execution of asynchronous callbacks.
*
* @method _schedule
* @param callback {Object} the callback object to execute
* @return {Boolean} whether the run loop should continue
* @protected
*/
_schedule : function (callback) {
this._running = Y.later(callback.timeout, this, function () {
if (this._execute(callback)) {
this.run();
}
});
return false;
},
/**
* Determines if the queue is waiting for a callback to complete execution.
*
* @method isRunning
* @return {Boolean} true if queue is waiting for a
* from any initiated transactions
*/
isRunning : function () {
return !!this._running;
},
/**
* Default functionality for the &quot;execute&quot; event. Executes the
* callback function
*
* @method _defExecFn
* @param e {Event} the event object
* @protected
*/
_defExecFn : function (e) {
e.callback();
},
/**
* Add any number of callbacks to the end of the queue. Callbacks may be
* provided as functions or objects.
*
* @method add
* @param callback* {Function|Object} 0..n callbacks
* @return {AsyncQueue} the AsyncQueue instance
* @chainable
*/
add : function () {
this.fire('add', { callbacks: Y.Array(arguments,0,true) });
return this;
},
/**
* Default functionality for the &quot;add&quot; event. Adds the callbacks
* in the event facade to the queue. Callbacks successfully added to the
* queue are present in the event's <code>added</code> property in the
* after phase.
*
* @method _defAddFn
* @param e {Event} the event object
* @protected
*/
_defAddFn : function(e) {
var _q = this._q,
added = [];
Y.Array.each(e.callbacks, function (c) {
if (isObject(c)) {
_q.push(c);
added.push(c);
}
});
e.added = added;
},
/**
* Pause the execution of the queue after the execution of the current
* callback completes. If called from code outside of a queued callback,
* clears the timeout for the pending callback. Paused queue can be
* restarted with q.run()
*
* @method pause
* @return {AsyncQueue} the AsyncQueue instance
* @chainable
*/
pause: function () {
if (isObject(this._running)) {
this._running.cancel();
}
this._running = false;
return this;
},
/**
* Stop and clear the queue after the current execution of the
* current callback completes.
*
* @method stop
* @return {AsyncQueue} the AsyncQueue instance
* @chainable
*/
stop : function () {
this._q = [];
return this.pause();
},
/**
* Returns the current index of a callback. Pass in either the id or
* callback function from getCallback.
*
* @method indexOf
* @param callback {String|Function} the callback or its specified id
* @return {Number} index of the callback or -1 if not found
*/
indexOf : function (callback) {
var i = 0, len = this._q.length, c;
for (; i < len; ++i) {
c = this._q[i];
if (c === callback || c.id === callback) {
return i;
}
}
return -1;
},
/**
* Retrieve a callback by its id. Useful to modify the configuration
* while the queue is running.
*
* @method getCallback
* @param id {String} the id assigned to the callback
* @return {Object} the callback object
*/
getCallback : function (id) {
var i = this.indexOf(id);
return (i > -1) ? this._q[i] : null;
},
/**
* Promotes the named callback to the top of the queue. If a callback is
* currently executing or looping (via until or iterations), the promotion
* is scheduled to occur after the current callback has completed.
*
* @method promote
* @param callback {String|Object} the callback object or a callback's id
* @return {AsyncQueue} the AsyncQueue instance
* @chainable
*/
promote : function (callback) {
var payload = { callback : callback },e;
if (this.isRunning()) {
e = this.after(SHIFT, function () {
this.fire(PROMOTE, payload);
e.detach();
}, this);
} else {
this.fire(PROMOTE, payload);
}
return this;
},
/**
* <p>Default functionality for the &quot;promote&quot; event. Promotes the
* named callback to the head of the queue.</p>
*
* <p>The event object will contain a property &quot;callback&quot;, which
* holds the id of a callback or the callback object itself.</p>
*
* @method _defPromoteFn
* @param e {Event} the custom event
* @protected
*/
_defPromoteFn : function (e) {
var i = this.indexOf(e.callback),
promoted = (i > -1) ? this._q.splice(i,1)[0] : null;
e.promoted = promoted;
if (promoted) {
this._q.unshift(promoted);
}
},
/**
* Removes the callback from the queue. If the queue is active, the
* removal is scheduled to occur after the current callback has completed.
*
* @method remove
* @param callback {String|Object} the callback object or a callback's id
* @return {AsyncQueue} the AsyncQueue instance
* @chainable
*/
remove : function (callback) {
var payload = { callback : callback },e;
// Can't return the removed callback because of the deferral until
// current callback is complete
if (this.isRunning()) {
e = this.after(SHIFT, function () {
this.fire(REMOVE, payload);
e.detach();
},this);
} else {
this.fire(REMOVE, payload);
}
return this;
},
/**
* <p>Default functionality for the &quot;remove&quot; event. Removes the
* callback from the queue.</p>
*
* <p>The event object will contain a property &quot;callback&quot;, which
* holds the id of a callback or the callback object itself.</p>
*
* @method _defRemoveFn
* @param e {Event} the custom event
* @protected
*/
_defRemoveFn : function (e) {
var i = this.indexOf(e.callback);
e.removed = (i > -1) ? this._q.splice(i,1)[0] : null;
},
/**
* Returns the number of callbacks in the queue.
*
* @method size
* @return {Number}
*/
size : function () {
// next() flushes callbacks that have met their until() criteria and
// therefore shouldn't count since they wouldn't execute anyway.
if (!this.isRunning()) {
this.next();
}
return this._q.length;
}
});
}, '3.0.0' ,{requires:['event-custom']});

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("attribute-complex",function(B){var A=B.Object,C=".";B.Attribute.Complex=function(){};B.Attribute.Complex.prototype={_normAttrVals:function(G){var I={},H={},J,D,F,E;if(G){for(E in G){if(G.hasOwnProperty(E)){if(E.indexOf(C)!==-1){J=E.split(C);D=J.shift();F=H[D]=H[D]||[];F[F.length]={path:J,value:G[E]};}else{I[E]=G[E];}}}return{simple:I,complex:H};}else{return null;}},_getAttrInitVal:function(K,I,M){var E=(I.valueFn)?I.valueFn.call(this):I.value,D,F,H,G,N,L,J;if(!I.readOnly&&M){D=M.simple;if(D&&D.hasOwnProperty(K)){E=D[K];}F=M.complex;if(F&&F.hasOwnProperty(K)){J=F[K];for(H=0,G=J.length;H<G;++H){N=J[H].path;L=J[H].value;A.setValue(E,N,L);}}}return E;}};B.mix(B.Attribute,B.Attribute.Complex,true,null,1);},"3.0.0",{requires:["attribute-base"]});

View File

@@ -0,0 +1,120 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('attribute-complex', function(Y) {
/**
* Adds support for attribute providers to handle complex attributes in the constructor
*
* @module attribute
* @submodule attribute-complex
* @for Attribute
*/
var O = Y.Object,
DOT = ".";
Y.Attribute.Complex = function() {};
Y.Attribute.Complex.prototype = {
/**
* Utility method to split out simple attribute name/value pairs ("x")
* from complex attribute name/value pairs ("x.y.z"), so that complex
* attributes can be keyed by the top level attribute name.
*
* @method _normAttrVals
* @param {Object} valueHash An object with attribute name/value pairs
*
* @return {Object} An object literal with 2 properties - "simple" and "complex",
* containing simple and complex attribute values respectively keyed
* by the top level attribute name, or null, if valueHash is falsey.
*
* @private
*/
_normAttrVals : function(valueHash) {
var vals = {},
subvals = {},
path,
attr,
v, k;
if (valueHash) {
for (k in valueHash) {
if (valueHash.hasOwnProperty(k)) {
if (k.indexOf(DOT) !== -1) {
path = k.split(DOT);
attr = path.shift();
v = subvals[attr] = subvals[attr] || [];
v[v.length] = {
path : path,
value: valueHash[k]
};
} else {
vals[k] = valueHash[k];
}
}
}
return { simple:vals, complex:subvals };
} else {
return null;
}
},
/**
* Returns the initial value of the given attribute from
* either the default configuration provided, or the
* over-ridden value if it exists in the set of initValues
* provided and the attribute is not read-only.
*
* @param {String} attr The name of the attribute
* @param {Object} cfg The attribute configuration object
* @param {Object} initValues The object with simple and complex attribute name/value pairs returned from _normAttrVals
*
* @return {Any} The initial value of the attribute.
*
* @method _getAttrInitVal
* @private
*/
_getAttrInitVal : function(attr, cfg, initValues) {
var val = (cfg.valueFn) ? cfg.valueFn.call(this) : cfg.value,
simple,
complex,
i,
l,
path,
subval,
subvals;
if (!cfg.readOnly && initValues) {
// Simple Attributes
simple = initValues.simple;
if (simple && simple.hasOwnProperty(attr)) {
val = simple[attr];
}
// Complex Attributes (complex values applied, after simple, incase both are set)
complex = initValues.complex;
if (complex && complex.hasOwnProperty(attr)) {
subvals = complex[attr];
for (i = 0, l = subvals.length; i < l; ++i) {
path = subvals[i].path;
subval = subvals[i].value;
O.setValue(val, path, subval);
}
}
}
return val;
}
};
Y.mix(Y.Attribute, Y.Attribute.Complex, true, null, 1);
}, '3.0.0' ,{requires:['attribute-base']});

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("base-base",function(B){var H=B.Object,J=B.Lang,I=".",F="destroy",P="init",N="initialized",G="destroyed",D="initializer",C=Object.prototype.constructor,K="deep",Q="shallow",M="destructor",A=B.Attribute;function E(){A.call(this);var L=B.Plugin&&B.Plugin.Host;if(this._initPlugins&&L){L.call(this);}if(this._lazyAddAttrs!==false){this._lazyAddAttrs=true;}this.init.apply(this,arguments);}E._ATTR_CFG=A._ATTR_CFG.concat("cloneDefaultValue");E.NAME="base";E.ATTRS={initialized:{readOnly:true,value:false},destroyed:{readOnly:true,value:false}};E.prototype={init:function(L){this._yuievt.config.prefix=this.name=this.constructor.NAME;this.publish(P,{queuable:false,defaultFn:this._defInitFn});if(L){if(L.on){this.on(L.on);}if(L.after){this.after(L.after);}}this.fire(P,{cfg:L});return this;},destroy:function(){this.publish(F,{queuable:false,defaultFn:this._defDestroyFn});this.fire(F);return this;},_defInitFn:function(L){this._initHierarchy(L.cfg);if(this._initPlugins){this._initPlugins(L.cfg);}this._set(N,true);},_defDestroyFn:function(L){this._destroyHierarchy();if(this._destroyPlugins){this._destroyPlugins();}this._set(G,true);},_getClasses:function(){if(!this._classes){this._initHierarchyData();}return this._classes;},_getAttrCfgs:function(){if(!this._attrs){this._initHierarchyData();}return this._attrs;},_filterAttrCfgs:function(T,O){var R=null,L,S=T.ATTRS;if(S){for(L in S){if(S.hasOwnProperty(L)&&O[L]){R=R||{};R[L]=O[L];delete O[L];}}}return R;},_initHierarchyData:function(){var R=this.constructor,O=[],L=[];while(R){O[O.length]=R;if(R.ATTRS){L[L.length]=R.ATTRS;}R=R.superclass?R.superclass.constructor:null;}this._classes=O;this._attrs=this._aggregateAttrs(L);},_aggregateAttrs:function(W){var T,X,S,L,Y,O,V,R=E._ATTR_CFG,U={};if(W){for(O=W.length-1;O>=0;--O){X=W[O];for(T in X){if(X.hasOwnProperty(T)){S=B.mix({},X[T],true,R);L=S.value;V=S.cloneDefaultValue;if(L){if((V===undefined&&(C===L.constructor||J.isArray(L)))||V===K||V===true){S.value=B.clone(L);}else{if(V===Q){S.value=B.merge(L);}}}Y=null;if(T.indexOf(I)!==-1){Y=T.split(I);T=Y.shift();}if(Y&&U[T]&&U[T].value){H.setValue(U[T].value,Y,L);}else{if(!Y){if(!U[T]){U[T]=S;}else{B.mix(U[T],S,true,R);}}}}}}}return U;},_initHierarchy:function(U){var R=this._lazyAddAttrs,V,W,X,S,O,T=this._getClasses(),L=this._getAttrCfgs();for(X=T.length-1;X>=0;X--){V=T[X];W=V.prototype;if(V._yuibuild&&V._yuibuild.exts&&!V._yuibuild.dynamic){for(S=0,O=V._yuibuild.exts.length;S<O;S++){V._yuibuild.exts[S].apply(this,arguments);}}this.addAttrs(this._filterAttrCfgs(V,L),U,R);if(W.hasOwnProperty(D)){W.initializer.apply(this,arguments);}}},_destroyHierarchy:function(){var T,O,S,L,R=this._getClasses();for(S=0,L=R.length;S<L;S++){T=R[S];O=T.prototype;if(O.hasOwnProperty(M)){O.destructor.apply(this,arguments);}}},toString:function(){return this.constructor.NAME+"["+B.stamp(this)+"]";}};B.mix(E,A,false,null,1);E.prototype.constructor=E;B.Base=E;E.prototype.constructor=E;},"3.0.0",{requires:["attribute-base"]});

View File

@@ -0,0 +1,531 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('base-base', function(Y) {
/**
* The base module provides the Base class, which objects requiring attribute and custom event support can extend.
* The module also provides two ways to reuse code - An augmentable Plugin.Host interface which provides plugin support
* (which is augmented to the Base class) and Base.build which provides a way to
* build custom classes using extensions.
*
* @module base
*/
/**
* The base-base submodule provides the Base class without the Plugin support, provided by Plugin.Host,
* and without the extension support provided by Base.build.
*
* @module base
* @submodule base-base
*/
var O = Y.Object,
L = Y.Lang,
DOT = ".",
DESTROY = "destroy",
INIT = "init",
INITIALIZED = "initialized",
DESTROYED = "destroyed",
INITIALIZER = "initializer",
OBJECT_CONSTRUCTOR = Object.prototype.constructor,
DEEP = "deep",
SHALLOW = "shallow",
DESTRUCTOR = "destructor",
Attribute = Y.Attribute;
/**
* <p>
* A base class which objects requiring attributes and custom event support can
* extend. Base also handles the chaining of initializer and destructor methods across
* the hierarchy as part of object construction and destruction. Additionally, attributes configured
* through the static <a href="#property_Base.ATTRS">ATTRS</a> property for each class
* in the hierarchy will be initialized by Base.
* </p>
*
* <p>
* The static <a href="#property_Base.NAME">NAME</a> property of each class extending
* from Base will be used as the identifier for the class, and is used by Base to prefix
* all events fired by instances of that class.
* </p>
* @class Base
* @constructor
* @uses Attribute
* @uses Plugin.Host
*
* @param {Object} config Object with configuration property name/value pairs
*/
function Base() {
Attribute.call(this);
// If Plugin.Host has been augmented [ through base-pluginhost ], setup it's
// initial state, but don't initialize Plugins yet. That's done after initialization.
var PluginHost = Y.Plugin && Y.Plugin.Host;
if (this._initPlugins && PluginHost) {
PluginHost.call(this);
}
if (this._lazyAddAttrs !== false) { this._lazyAddAttrs = true; }
this.init.apply(this, arguments);
}
/**
* The list of properties which can be configured for
* each attribute (e.g. setter, getter, writeOnce, readOnly etc.)
*
* @property Base._ATTR_CFG
* @type Array
* @static
* @private
*/
Base._ATTR_CFG = Attribute._ATTR_CFG.concat("cloneDefaultValue");
/**
* <p>
* The string to be used to identify instances of
* this class, for example in prefixing events.
* </p>
* <p>
* Classes extending Base, should define their own
* static NAME property, which should be camelCase by
* convention (e.g. MyClass.NAME = "myClass";).
* </p>
* @property Base.NAME
* @type String
* @static
*/
Base.NAME = "base";
/**
* The default set of attributes which will be available for instances of this class, and
* their configuration. In addition to the configuration properties listed by
* Attribute's <a href="Attribute.html#method_addAttr">addAttr</a> method, the attribute
* can also be configured with a "cloneDefaultValue" property, which defines how the statically
* defined value field should be protected ("shallow", "deep" and false are supported values).
*
* By default if the value is an object literal or an array it will be "shallow" cloned, to
* protect the default value.
*
* @property Base.ATTRS
* @type Object
* @static
*/
Base.ATTRS = {
/**
* Flag indicating whether or not this object
* has been through the init lifecycle phase.
*
* @attribute initialized
* @readonly
* @default false
* @type boolean
*/
initialized: {
readOnly:true,
value:false
},
/**
* Flag indicating whether or not this object
* has been through the destroy lifecycle phase.
*
* @attribute destroyed
* @readonly
* @default false
* @type boolean
*/
destroyed: {
readOnly:true,
value:false
}
};
Base.prototype = {
/**
* Init lifecycle method, invoked during construction.
* Fires the init event prior to setting up attributes and
* invoking initializers for the class hierarchy.
*
* @method init
* @final
* @chainable
* @param {Object} config Object with configuration property name/value pairs
* @return {Base} A reference to this object
*/
init: function(config) {
/**
* The string used to identify the class of this object.
*
* @deprecated Use this.constructor.NAME
* @property name
* @type String
*/
this._yuievt.config.prefix = this.name = this.constructor.NAME;
/**
* <p>
* Lifecycle event for the init phase, fired prior to initialization.
* Invoking the preventDefault() method on the event object provided
* to subscribers will prevent initialization from occuring.
* </p>
* <p>
* Subscribers to the "after" momemt of this event, will be notified
* after initialization of the object is complete (and therefore
* cannot prevent initialization).
* </p>
*
* @event init
* @preventable _defInitFn
* @param {EventFacade} e Event object, with a cfg property which
* refers to the configuration object passed to the constructor.
*/
this.publish(INIT, {
queuable:false,
defaultFn:this._defInitFn
});
if (config) {
if (config.on) {
this.on(config.on);
}
if (config.after) {
this.after(config.after);
}
}
this.fire(INIT, {cfg: config});
return this;
},
/**
* <p>
* Destroy lifecycle method. Fires the destroy
* event, prior to invoking destructors for the
* class hierarchy.
* </p>
* <p>
* Subscribers to the destroy
* event can invoke preventDefault on the event object, to prevent destruction
* from proceeding.
* </p>
* @method destroy
* @return {Base} A reference to this object
* @final
* @chainable
*/
destroy: function() {
/**
* <p>
* Lifecycle event for the destroy phase,
* fired prior to destruction. Invoking the preventDefault
* method on the event object provided to subscribers will
* prevent destruction from proceeding.
* </p>
* <p>
* Subscribers to the "after" moment of this event, will be notified
* after destruction is complete (and as a result cannot prevent
* destruction).
* </p>
* @event destroy
* @preventable _defDestroyFn
* @param {EventFacade} e Event object
*/
this.publish(DESTROY, {
queuable:false,
defaultFn: this._defDestroyFn
});
this.fire(DESTROY);
return this;
},
/**
* Default init event handler
*
* @method _defInitFn
* @param {EventFacade} e Event object, with a cfg property which
* refers to the configuration object passed to the constructor.
* @protected
*/
_defInitFn : function(e) {
this._initHierarchy(e.cfg);
if (this._initPlugins) {
// Need to initPlugins manually, to handle constructor parsing, static Plug parsing
this._initPlugins(e.cfg);
}
this._set(INITIALIZED, true);
},
/**
* Default destroy event handler
*
* @method _defDestroyFn
* @param {EventFacade} e Event object
* @protected
*/
_defDestroyFn : function(e) {
this._destroyHierarchy();
if (this._destroyPlugins) {
this._destroyPlugins();
}
this._set(DESTROYED, true);
},
/**
* Returns the class hierarchy for this object, with Base being the last class in the array.
*
* @method _getClasses
* @protected
* @return {Function[]} An array of classes (constructor functions), making up the class hierarchy for this object.
* This value is cached the first time the method, or _getAttrCfgs, is invoked. Subsequent invocations return the
* cached value.
*/
_getClasses : function() {
if (!this._classes) {
this._initHierarchyData();
}
return this._classes;
},
/**
* Returns an aggregated set of attribute configurations, by traversing the class hierarchy.
*
* @method _getAttrCfgs
* @protected
* @return {Object} The hash of attribute configurations, aggregated across classes in the hierarchy
* This value is cached the first time the method, or _getClasses, is invoked. Subsequent invocations return
* the cached value.
*/
_getAttrCfgs : function() {
if (!this._attrs) {
this._initHierarchyData();
}
return this._attrs;
},
/**
* A helper method used when processing ATTRS across the class hierarchy during
* initialization. Returns a disposable object with the attributes defined for
* the provided class, extracted from the set of all attributes passed in .
*
* @method _filterAttrCfs
* @private
*
* @param {Function} clazz The class for which the desired attributes are required.
* @param {Object} allCfgs The set of all attribute configurations for this instance.
* Attributes will be removed from this set, if they belong to the filtered class, so
* that by the time all classes are processed, allCfgs will be empty.
*
* @return {Object} The set of attributes belonging to the class passed in, in the form
* of an object with attribute name/configuration pairs.
*/
_filterAttrCfgs : function(clazz, allCfgs) {
var cfgs = null, attr, attrs = clazz.ATTRS;
if (attrs) {
for (attr in attrs) {
if (attrs.hasOwnProperty(attr) && allCfgs[attr]) {
cfgs = cfgs || {};
cfgs[attr] = allCfgs[attr];
delete allCfgs[attr];
}
}
}
return cfgs;
},
/**
* A helper method used by _getClasses and _getAttrCfgs, which determines both
* the array of classes and aggregate set of attribute configurations
* across the class hierarchy for the instance.
*
* @method _initHierarchyData
* @private
*/
_initHierarchyData : function() {
var c = this.constructor,
classes = [],
attrs = [];
while (c) {
// Add to classes
classes[classes.length] = c;
// Add to attributes
if (c.ATTRS) {
attrs[attrs.length] = c.ATTRS;
}
c = c.superclass ? c.superclass.constructor : null;
}
this._classes = classes;
this._attrs = this._aggregateAttrs(attrs);
},
/**
* A helper method, used by _initHierarchyData to aggregate
* attribute configuration across the instances class hierarchy.
*
* The method will potect the attribute configuration value to protect the statically defined
* default value in ATTRS if required (if the value is an object literal, array or the
* attribute configuration has cloneDefaultValue set to shallow or deep).
*
* @method _aggregateAttrs
* @private
* @param {Array} allAttrs An array of ATTRS definitions across classes in the hierarchy
* (subclass first, Base last)
* @return {Object} The aggregate set of ATTRS definitions for the instance
*/
_aggregateAttrs : function(allAttrs) {
var attr,
attrs,
cfg,
val,
path,
i,
clone,
cfgProps = Base._ATTR_CFG,
aggAttrs = {};
if (allAttrs) {
for (i = allAttrs.length-1; i >= 0; --i) {
attrs = allAttrs[i];
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
// Protect config passed in
cfg = Y.mix({}, attrs[attr], true, cfgProps);
val = cfg.value;
clone = cfg.cloneDefaultValue;
if (val) {
if ( (clone === undefined && (OBJECT_CONSTRUCTOR === val.constructor || L.isArray(val))) || clone === DEEP || clone === true) {
cfg.value = Y.clone(val);
} else if (clone === SHALLOW) {
cfg.value = Y.merge(val);
}
// else if (clone === false), don't clone the static default value.
// It's intended to be used by reference.
}
path = null;
if (attr.indexOf(DOT) !== -1) {
path = attr.split(DOT);
attr = path.shift();
}
if (path && aggAttrs[attr] && aggAttrs[attr].value) {
O.setValue(aggAttrs[attr].value, path, val);
} else if (!path){
if (!aggAttrs[attr]) {
aggAttrs[attr] = cfg;
} else {
Y.mix(aggAttrs[attr], cfg, true, cfgProps);
}
}
}
}
}
}
return aggAttrs;
},
/**
* Initializes the class hierarchy for the instance, which includes
* initializing attributes for each class defined in the class's
* static <a href="#property_Base.ATTRS">ATTRS</a> property and
* invoking the initializer method on the prototype of each class in the hierarchy.
*
* @method _initHierarchy
* @param {Object} userVals Object with configuration property name/value pairs
* @private
*/
_initHierarchy : function(userVals) {
var lazy = this._lazyAddAttrs,
constr,
constrProto,
ci,
ei,
el,
classes = this._getClasses(),
attrCfgs = this._getAttrCfgs();
for (ci = classes.length-1; ci >= 0; ci--) {
constr = classes[ci];
constrProto = constr.prototype;
if (constr._yuibuild && constr._yuibuild.exts && !constr._yuibuild.dynamic) {
for (ei = 0, el = constr._yuibuild.exts.length; ei < el; ei++) {
constr._yuibuild.exts[ei].apply(this, arguments);
}
}
this.addAttrs(this._filterAttrCfgs(constr, attrCfgs), userVals, lazy);
if (constrProto.hasOwnProperty(INITIALIZER)) {
constrProto.initializer.apply(this, arguments);
}
}
},
/**
* Destroys the class hierarchy for this instance by invoking
* the descructor method on the prototype of each class in the hierarchy.
*
* @method _destroyHierarchy
* @private
*/
_destroyHierarchy : function() {
var constr,
constrProto,
ci, cl,
classes = this._getClasses();
for (ci = 0, cl = classes.length; ci < cl; ci++) {
constr = classes[ci];
constrProto = constr.prototype;
if (constrProto.hasOwnProperty(DESTRUCTOR)) {
constrProto.destructor.apply(this, arguments);
}
}
},
/**
* Default toString implementation. Provides the constructor NAME
* and the instance ID.
*
* @method toString
* @return {String} String representation for this object
*/
toString: function() {
return this.constructor.NAME + "[" + Y.stamp(this) + "]";
}
};
// Straightup augment, no wrapper functions
Y.mix(Base, Attribute, false, null, 1);
// Fix constructor
Base.prototype.constructor = Base;
Y.Base = Base;
// Fix constructor
Base.prototype.constructor = Base;
}, '3.0.0' ,{requires:['attribute-base']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("base-build",function(C){var B=C.Base,A=C.Lang;B._buildCfg={aggregates:["ATTRS","_PLUG","_UNPLUG"]};B.build=function(D,I,M,L){var O=B.build,E=O._getClass(I,L),K=O._getAggregates(I,L),G=E._yuibuild.dynamic,J,H,F,N;if(G){if(K){for(J=0,H=K.length;J<H;++J){F=K[J];if(I.hasOwnProperty(F)){E[F]=A.isArray(I[F])?[]:{};}}C.aggregate(E,I,true,K);}}for(J=0,H=M.length;J<H;J++){N=M[J];if(K){C.aggregate(E,N,true,K);}C.mix(E,N,true,null,1);E._yuibuild.exts.push(N);}E.prototype.hasImpl=O._hasImpl;if(G){E.NAME=D;E.prototype.constructor=E;}return E;};C.mix(B.build,{_template:function(D){function E(){E.superclass.constructor.apply(this,arguments);var H=E._yuibuild.exts,F=H.length,G;for(G=0;G<F;G++){H[G].apply(this,arguments);}return this;}C.extend(E,D);return E;},_hasImpl:function(G){var J=this._getClasses();for(var I=0,E=J.length;I<E;I++){var D=J[I];if(D._yuibuild){var H=D._yuibuild.exts,K=H.length,F;for(F=0;F<K;F++){if(H[F]===G){return true;}}}}return false;},_getClass:function(D,E){var F=(E&&false===E.dynamic)?false:true,G=(F)?B.build._template(D):D;G._yuibuild={id:null,exts:[],dynamic:F};return G;},_getAggregates:function(D,E){var F=[],H=(E&&E.aggregates),I=D,G;while(I&&I.prototype){G=I._buildCfg&&I._buildCfg.aggregates;if(G){F=F.concat(G);}I=I.superclass?I.superclass.constructor:null;}if(H){F=F.concat(H);}return F;}});},"3.0.0",{requires:["base-base"]});

View File

@@ -0,0 +1,201 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('base-build', function(Y) {
/**
* The base-build submodule provides Base.build functionality, which
* can be used to create custom classes, by aggregating extensions onto
* a main class.
*
* @module base
* @submodule base-build
* @for Base
*/
var Base = Y.Base,
L = Y.Lang;
/**
* The build configuration for the Base class.
*
* Defines the static fields which need to be aggregated
* when the Base class is used as the main class passed to
* the <a href="#method_Base.build">Base.build</a> method.
*
* @property Base._buildCfg
* @type Object
* @static
* @final
* @private
*/
Base._buildCfg = {
aggregates : ["ATTRS", "_PLUG", "_UNPLUG"]
};
/**
* <p>
* Builds a custom constructor function (class) from the
* main function, and array of extension functions (classes)
* provided. The NAME field for the constructor function is
* defined by the first argument passed in.
* </p>
* <p>
* The cfg object supports the following properties
* </p>
* <dl>
* <dt>dynamic &#60;boolean&#62;</dt>
* <dd>
* <p>If true (default), a completely new class
* is created which extends the main class, and acts as the
* host on which the extension classes are augmented.</p>
* <p>If false, the extensions classes are augmented directly to
* the main class, modifying the main class' prototype.</p>
* </dd>
* <dt>aggregates &#60;String[]&#62;</dt>
* <dd>An array of static property names, which will get aggregated
* on to the built class, in addition to the default properties build
* will always aggregate as defined by the main class' static _buildCfg
* property.
* </dd>
* </dl>
*
* @method Base.build
* @static
* @param {Function} name The name of the new class. Used to defined the NAME property for the new class.
* @param {Function} main The main class on which to base the built class
* @param {Function[]} extensions The set of extension classes which will be
* augmented/aggregated to the built class.
* @param {Object} cfg Optional. Build configuration for the class (see description).
* @return {Function} A custom class, created from the provided main and extension classes
*/
Base.build = function(name, main, extensions, cfg) {
var build = Base.build,
builtClass = build._getClass(main, cfg),
aggregates = build._getAggregates(main, cfg),
dynamic = builtClass._yuibuild.dynamic,
i, l, val, extClass;
// Shallow isolate aggregates
if (dynamic) {
if (aggregates) {
for (i = 0, l = aggregates.length; i < l; ++i) {
val = aggregates[i];
if (main.hasOwnProperty(val)) {
builtClass[val] = L.isArray(main[val]) ? [] : {};
}
}
Y.aggregate(builtClass, main, true, aggregates);
}
}
// Augment/Aggregate
for (i = 0, l = extensions.length; i < l; i++) {
extClass = extensions[i];
if (aggregates) {
Y.aggregate(builtClass, extClass, true, aggregates);
}
// Old augment
Y.mix(builtClass, extClass, true, null, 1);
builtClass._yuibuild.exts.push(extClass);
}
builtClass.prototype.hasImpl = build._hasImpl;
if (dynamic) {
builtClass.NAME = name;
builtClass.prototype.constructor = builtClass;
}
return builtClass;
};
Y.mix(Base.build, {
_template: function(main) {
function BuiltClass() {
BuiltClass.superclass.constructor.apply(this, arguments);
var f = BuiltClass._yuibuild.exts,
l = f.length,
i;
for (i = 0; i < l; i++) {
f[i].apply(this, arguments);
}
return this;
}
Y.extend(BuiltClass, main);
return BuiltClass;
},
_hasImpl : function(extClass) {
var classes = this._getClasses();
for (var i = 0, l = classes.length; i < l; i++) {
var cls = classes[i];
if (cls._yuibuild) {
var exts = cls._yuibuild.exts,
ll = exts.length,
j;
for (j = 0; j < ll; j++) {
if (exts[j] === extClass) {
return true;
}
}
}
}
return false;
},
_getClass : function(main, cfg) {
var dynamic = (cfg && false === cfg.dynamic) ? false : true,
builtClass = (dynamic) ? Base.build._template(main) : main;
builtClass._yuibuild = {
id: null,
exts : [],
dynamic : dynamic
};
return builtClass;
},
_getAggregates : function(main, cfg) {
var aggr = [],
cfgAggr = (cfg && cfg.aggregates),
c = main,
classAggr;
while (c && c.prototype) {
classAggr = c._buildCfg && c._buildCfg.aggregates;
if (classAggr) {
aggr = aggr.concat(classAggr);
}
c = c.superclass ? c.superclass.constructor : null;
}
if (cfgAggr) {
aggr = aggr.concat(cfgAggr);
}
return aggr;
}
});
}, '3.0.0' ,{requires:['base-base']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("base-base",function(B){var H=B.Object,J=B.Lang,I=".",F="destroy",P="init",N="initialized",G="destroyed",D="initializer",C=Object.prototype.constructor,K="deep",Q="shallow",M="destructor",A=B.Attribute;function E(){A.call(this);var L=B.Plugin&&B.Plugin.Host;if(this._initPlugins&&L){L.call(this);}if(this._lazyAddAttrs!==false){this._lazyAddAttrs=true;}this.init.apply(this,arguments);}E._ATTR_CFG=A._ATTR_CFG.concat("cloneDefaultValue");E.NAME="base";E.ATTRS={initialized:{readOnly:true,value:false},destroyed:{readOnly:true,value:false}};E.prototype={init:function(L){this._yuievt.config.prefix=this.name=this.constructor.NAME;this.publish(P,{queuable:false,defaultFn:this._defInitFn});if(L){if(L.on){this.on(L.on);}if(L.after){this.after(L.after);}}this.fire(P,{cfg:L});return this;},destroy:function(){this.publish(F,{queuable:false,defaultFn:this._defDestroyFn});this.fire(F);return this;},_defInitFn:function(L){this._initHierarchy(L.cfg);if(this._initPlugins){this._initPlugins(L.cfg);}this._set(N,true);},_defDestroyFn:function(L){this._destroyHierarchy();if(this._destroyPlugins){this._destroyPlugins();}this._set(G,true);},_getClasses:function(){if(!this._classes){this._initHierarchyData();}return this._classes;},_getAttrCfgs:function(){if(!this._attrs){this._initHierarchyData();}return this._attrs;},_filterAttrCfgs:function(T,O){var R=null,L,S=T.ATTRS;if(S){for(L in S){if(S.hasOwnProperty(L)&&O[L]){R=R||{};R[L]=O[L];delete O[L];}}}return R;},_initHierarchyData:function(){var R=this.constructor,O=[],L=[];while(R){O[O.length]=R;if(R.ATTRS){L[L.length]=R.ATTRS;}R=R.superclass?R.superclass.constructor:null;}this._classes=O;this._attrs=this._aggregateAttrs(L);},_aggregateAttrs:function(W){var T,X,S,L,Y,O,V,R=E._ATTR_CFG,U={};if(W){for(O=W.length-1;O>=0;--O){X=W[O];for(T in X){if(X.hasOwnProperty(T)){S=B.mix({},X[T],true,R);L=S.value;V=S.cloneDefaultValue;if(L){if((V===undefined&&(C===L.constructor||J.isArray(L)))||V===K||V===true){S.value=B.clone(L);}else{if(V===Q){S.value=B.merge(L);}}}Y=null;if(T.indexOf(I)!==-1){Y=T.split(I);T=Y.shift();}if(Y&&U[T]&&U[T].value){H.setValue(U[T].value,Y,L);}else{if(!Y){if(!U[T]){U[T]=S;}else{B.mix(U[T],S,true,R);}}}}}}}return U;},_initHierarchy:function(U){var R=this._lazyAddAttrs,V,W,X,S,O,T=this._getClasses(),L=this._getAttrCfgs();for(X=T.length-1;X>=0;X--){V=T[X];W=V.prototype;if(V._yuibuild&&V._yuibuild.exts&&!V._yuibuild.dynamic){for(S=0,O=V._yuibuild.exts.length;S<O;S++){V._yuibuild.exts[S].apply(this,arguments);}}this.addAttrs(this._filterAttrCfgs(V,L),U,R);if(W.hasOwnProperty(D)){W.initializer.apply(this,arguments);}}},_destroyHierarchy:function(){var T,O,S,L,R=this._getClasses();for(S=0,L=R.length;S<L;S++){T=R[S];O=T.prototype;if(O.hasOwnProperty(M)){O.destructor.apply(this,arguments);}}},toString:function(){return this.constructor.NAME+"["+B.stamp(this)+"]";}};B.mix(E,A,false,null,1);E.prototype.constructor=E;B.Base=E;E.prototype.constructor=E;},"3.0.0",{requires:["attribute-base"]});YUI.add("base-pluginhost",function(C){var A=C.Base,B=C.Plugin.Host;C.mix(A,B,false,null,1);A.plug=B.plug;A.unplug=B.unplug;},"3.0.0",{requires:["base-base","pluginhost"]});YUI.add("base-build",function(C){var B=C.Base,A=C.Lang;B._buildCfg={aggregates:["ATTRS","_PLUG","_UNPLUG"]};B.build=function(D,I,M,L){var O=B.build,E=O._getClass(I,L),K=O._getAggregates(I,L),G=E._yuibuild.dynamic,J,H,F,N;if(G){if(K){for(J=0,H=K.length;J<H;++J){F=K[J];if(I.hasOwnProperty(F)){E[F]=A.isArray(I[F])?[]:{};}}C.aggregate(E,I,true,K);}}for(J=0,H=M.length;J<H;J++){N=M[J];if(K){C.aggregate(E,N,true,K);}C.mix(E,N,true,null,1);E._yuibuild.exts.push(N);}E.prototype.hasImpl=O._hasImpl;if(G){E.NAME=D;E.prototype.constructor=E;}return E;};C.mix(B.build,{_template:function(D){function E(){E.superclass.constructor.apply(this,arguments);var H=E._yuibuild.exts,F=H.length,G;for(G=0;G<F;G++){H[G].apply(this,arguments);}return this;}C.extend(E,D);return E;},_hasImpl:function(G){var J=this._getClasses();for(var I=0,E=J.length;I<E;I++){var D=J[I];if(D._yuibuild){var H=D._yuibuild.exts,K=H.length,F;for(F=0;F<K;F++){if(H[F]===G){return true;}}}}return false;},_getClass:function(D,E){var F=(E&&false===E.dynamic)?false:true,G=(F)?B.build._template(D):D;G._yuibuild={id:null,exts:[],dynamic:F};return G;},_getAggregates:function(D,E){var F=[],H=(E&&E.aggregates),I=D,G;while(I&&I.prototype){G=I._buildCfg&&I._buildCfg.aggregates;if(G){F=F.concat(G);}I=I.superclass?I.superclass.constructor:null;}if(H){F=F.concat(H);}return F;}});},"3.0.0",{requires:["base-base"]});YUI.add("base",function(A){},"3.0.0",{use:["base-base","base-pluginhost","base-build"]});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("base-pluginhost",function(C){var A=C.Base,B=C.Plugin.Host;C.mix(A,B,false,null,1);A.plug=B.plug;A.unplug=B.unplug;},"3.0.0",{requires:["base-base","pluginhost"]});

View File

@@ -0,0 +1,43 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('base-pluginhost', function(Y) {
/**
* The base-pluginhost submodule adds Plugin support to Base, by augmenting Base with
* Plugin.Host and setting up static (class level) Base.plug and Base.unplug methods.
*
* @module base
* @submodule base-pluginhost
* @for Base
*/
var Base = Y.Base,
PluginHost = Y.Plugin.Host;
Y.mix(Base, PluginHost, false, null, 1);
/**
* Alias for <a href="Plugin.Host.html#method_Plugin.Host.plug">Plugin.Host.plug</a>. See aliased
* method for argument and return value details.
*
* @method Base.plug
* @static
*/
Base.plug = PluginHost.plug;
/**
* Alias for <a href="Plugin.Host.html#method_Plugin.Host.unplug">Plugin.Host.unplug</a>. See the
* aliased method for argument and return value details.
*
* @method Base.unplug
* @static
*/
Base.unplug = PluginHost.unplug;
}, '3.0.0' ,{requires:['base-base', 'pluginhost']});

View File

@@ -0,0 +1,765 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('base-base', function(Y) {
/**
* The base module provides the Base class, which objects requiring attribute and custom event support can extend.
* The module also provides two ways to reuse code - An augmentable Plugin.Host interface which provides plugin support
* (which is augmented to the Base class) and Base.build which provides a way to
* build custom classes using extensions.
*
* @module base
*/
/**
* The base-base submodule provides the Base class without the Plugin support, provided by Plugin.Host,
* and without the extension support provided by Base.build.
*
* @module base
* @submodule base-base
*/
var O = Y.Object,
L = Y.Lang,
DOT = ".",
DESTROY = "destroy",
INIT = "init",
INITIALIZED = "initialized",
DESTROYED = "destroyed",
INITIALIZER = "initializer",
OBJECT_CONSTRUCTOR = Object.prototype.constructor,
DEEP = "deep",
SHALLOW = "shallow",
DESTRUCTOR = "destructor",
Attribute = Y.Attribute;
/**
* <p>
* A base class which objects requiring attributes and custom event support can
* extend. Base also handles the chaining of initializer and destructor methods across
* the hierarchy as part of object construction and destruction. Additionally, attributes configured
* through the static <a href="#property_Base.ATTRS">ATTRS</a> property for each class
* in the hierarchy will be initialized by Base.
* </p>
*
* <p>
* The static <a href="#property_Base.NAME">NAME</a> property of each class extending
* from Base will be used as the identifier for the class, and is used by Base to prefix
* all events fired by instances of that class.
* </p>
* @class Base
* @constructor
* @uses Attribute
* @uses Plugin.Host
*
* @param {Object} config Object with configuration property name/value pairs
*/
function Base() {
Attribute.call(this);
// If Plugin.Host has been augmented [ through base-pluginhost ], setup it's
// initial state, but don't initialize Plugins yet. That's done after initialization.
var PluginHost = Y.Plugin && Y.Plugin.Host;
if (this._initPlugins && PluginHost) {
PluginHost.call(this);
}
if (this._lazyAddAttrs !== false) { this._lazyAddAttrs = true; }
this.init.apply(this, arguments);
}
/**
* The list of properties which can be configured for
* each attribute (e.g. setter, getter, writeOnce, readOnly etc.)
*
* @property Base._ATTR_CFG
* @type Array
* @static
* @private
*/
Base._ATTR_CFG = Attribute._ATTR_CFG.concat("cloneDefaultValue");
/**
* <p>
* The string to be used to identify instances of
* this class, for example in prefixing events.
* </p>
* <p>
* Classes extending Base, should define their own
* static NAME property, which should be camelCase by
* convention (e.g. MyClass.NAME = "myClass";).
* </p>
* @property Base.NAME
* @type String
* @static
*/
Base.NAME = "base";
/**
* The default set of attributes which will be available for instances of this class, and
* their configuration. In addition to the configuration properties listed by
* Attribute's <a href="Attribute.html#method_addAttr">addAttr</a> method, the attribute
* can also be configured with a "cloneDefaultValue" property, which defines how the statically
* defined value field should be protected ("shallow", "deep" and false are supported values).
*
* By default if the value is an object literal or an array it will be "shallow" cloned, to
* protect the default value.
*
* @property Base.ATTRS
* @type Object
* @static
*/
Base.ATTRS = {
/**
* Flag indicating whether or not this object
* has been through the init lifecycle phase.
*
* @attribute initialized
* @readonly
* @default false
* @type boolean
*/
initialized: {
readOnly:true,
value:false
},
/**
* Flag indicating whether or not this object
* has been through the destroy lifecycle phase.
*
* @attribute destroyed
* @readonly
* @default false
* @type boolean
*/
destroyed: {
readOnly:true,
value:false
}
};
Base.prototype = {
/**
* Init lifecycle method, invoked during construction.
* Fires the init event prior to setting up attributes and
* invoking initializers for the class hierarchy.
*
* @method init
* @final
* @chainable
* @param {Object} config Object with configuration property name/value pairs
* @return {Base} A reference to this object
*/
init: function(config) {
/**
* The string used to identify the class of this object.
*
* @deprecated Use this.constructor.NAME
* @property name
* @type String
*/
this._yuievt.config.prefix = this.name = this.constructor.NAME;
/**
* <p>
* Lifecycle event for the init phase, fired prior to initialization.
* Invoking the preventDefault() method on the event object provided
* to subscribers will prevent initialization from occuring.
* </p>
* <p>
* Subscribers to the "after" momemt of this event, will be notified
* after initialization of the object is complete (and therefore
* cannot prevent initialization).
* </p>
*
* @event init
* @preventable _defInitFn
* @param {EventFacade} e Event object, with a cfg property which
* refers to the configuration object passed to the constructor.
*/
this.publish(INIT, {
queuable:false,
defaultFn:this._defInitFn
});
if (config) {
if (config.on) {
this.on(config.on);
}
if (config.after) {
this.after(config.after);
}
}
this.fire(INIT, {cfg: config});
return this;
},
/**
* <p>
* Destroy lifecycle method. Fires the destroy
* event, prior to invoking destructors for the
* class hierarchy.
* </p>
* <p>
* Subscribers to the destroy
* event can invoke preventDefault on the event object, to prevent destruction
* from proceeding.
* </p>
* @method destroy
* @return {Base} A reference to this object
* @final
* @chainable
*/
destroy: function() {
/**
* <p>
* Lifecycle event for the destroy phase,
* fired prior to destruction. Invoking the preventDefault
* method on the event object provided to subscribers will
* prevent destruction from proceeding.
* </p>
* <p>
* Subscribers to the "after" moment of this event, will be notified
* after destruction is complete (and as a result cannot prevent
* destruction).
* </p>
* @event destroy
* @preventable _defDestroyFn
* @param {EventFacade} e Event object
*/
this.publish(DESTROY, {
queuable:false,
defaultFn: this._defDestroyFn
});
this.fire(DESTROY);
return this;
},
/**
* Default init event handler
*
* @method _defInitFn
* @param {EventFacade} e Event object, with a cfg property which
* refers to the configuration object passed to the constructor.
* @protected
*/
_defInitFn : function(e) {
this._initHierarchy(e.cfg);
if (this._initPlugins) {
// Need to initPlugins manually, to handle constructor parsing, static Plug parsing
this._initPlugins(e.cfg);
}
this._set(INITIALIZED, true);
},
/**
* Default destroy event handler
*
* @method _defDestroyFn
* @param {EventFacade} e Event object
* @protected
*/
_defDestroyFn : function(e) {
this._destroyHierarchy();
if (this._destroyPlugins) {
this._destroyPlugins();
}
this._set(DESTROYED, true);
},
/**
* Returns the class hierarchy for this object, with Base being the last class in the array.
*
* @method _getClasses
* @protected
* @return {Function[]} An array of classes (constructor functions), making up the class hierarchy for this object.
* This value is cached the first time the method, or _getAttrCfgs, is invoked. Subsequent invocations return the
* cached value.
*/
_getClasses : function() {
if (!this._classes) {
this._initHierarchyData();
}
return this._classes;
},
/**
* Returns an aggregated set of attribute configurations, by traversing the class hierarchy.
*
* @method _getAttrCfgs
* @protected
* @return {Object} The hash of attribute configurations, aggregated across classes in the hierarchy
* This value is cached the first time the method, or _getClasses, is invoked. Subsequent invocations return
* the cached value.
*/
_getAttrCfgs : function() {
if (!this._attrs) {
this._initHierarchyData();
}
return this._attrs;
},
/**
* A helper method used when processing ATTRS across the class hierarchy during
* initialization. Returns a disposable object with the attributes defined for
* the provided class, extracted from the set of all attributes passed in .
*
* @method _filterAttrCfs
* @private
*
* @param {Function} clazz The class for which the desired attributes are required.
* @param {Object} allCfgs The set of all attribute configurations for this instance.
* Attributes will be removed from this set, if they belong to the filtered class, so
* that by the time all classes are processed, allCfgs will be empty.
*
* @return {Object} The set of attributes belonging to the class passed in, in the form
* of an object with attribute name/configuration pairs.
*/
_filterAttrCfgs : function(clazz, allCfgs) {
var cfgs = null, attr, attrs = clazz.ATTRS;
if (attrs) {
for (attr in attrs) {
if (attrs.hasOwnProperty(attr) && allCfgs[attr]) {
cfgs = cfgs || {};
cfgs[attr] = allCfgs[attr];
delete allCfgs[attr];
}
}
}
return cfgs;
},
/**
* A helper method used by _getClasses and _getAttrCfgs, which determines both
* the array of classes and aggregate set of attribute configurations
* across the class hierarchy for the instance.
*
* @method _initHierarchyData
* @private
*/
_initHierarchyData : function() {
var c = this.constructor,
classes = [],
attrs = [];
while (c) {
// Add to classes
classes[classes.length] = c;
// Add to attributes
if (c.ATTRS) {
attrs[attrs.length] = c.ATTRS;
}
c = c.superclass ? c.superclass.constructor : null;
}
this._classes = classes;
this._attrs = this._aggregateAttrs(attrs);
},
/**
* A helper method, used by _initHierarchyData to aggregate
* attribute configuration across the instances class hierarchy.
*
* The method will potect the attribute configuration value to protect the statically defined
* default value in ATTRS if required (if the value is an object literal, array or the
* attribute configuration has cloneDefaultValue set to shallow or deep).
*
* @method _aggregateAttrs
* @private
* @param {Array} allAttrs An array of ATTRS definitions across classes in the hierarchy
* (subclass first, Base last)
* @return {Object} The aggregate set of ATTRS definitions for the instance
*/
_aggregateAttrs : function(allAttrs) {
var attr,
attrs,
cfg,
val,
path,
i,
clone,
cfgProps = Base._ATTR_CFG,
aggAttrs = {};
if (allAttrs) {
for (i = allAttrs.length-1; i >= 0; --i) {
attrs = allAttrs[i];
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
// Protect config passed in
cfg = Y.mix({}, attrs[attr], true, cfgProps);
val = cfg.value;
clone = cfg.cloneDefaultValue;
if (val) {
if ( (clone === undefined && (OBJECT_CONSTRUCTOR === val.constructor || L.isArray(val))) || clone === DEEP || clone === true) {
cfg.value = Y.clone(val);
} else if (clone === SHALLOW) {
cfg.value = Y.merge(val);
}
// else if (clone === false), don't clone the static default value.
// It's intended to be used by reference.
}
path = null;
if (attr.indexOf(DOT) !== -1) {
path = attr.split(DOT);
attr = path.shift();
}
if (path && aggAttrs[attr] && aggAttrs[attr].value) {
O.setValue(aggAttrs[attr].value, path, val);
} else if (!path){
if (!aggAttrs[attr]) {
aggAttrs[attr] = cfg;
} else {
Y.mix(aggAttrs[attr], cfg, true, cfgProps);
}
}
}
}
}
}
return aggAttrs;
},
/**
* Initializes the class hierarchy for the instance, which includes
* initializing attributes for each class defined in the class's
* static <a href="#property_Base.ATTRS">ATTRS</a> property and
* invoking the initializer method on the prototype of each class in the hierarchy.
*
* @method _initHierarchy
* @param {Object} userVals Object with configuration property name/value pairs
* @private
*/
_initHierarchy : function(userVals) {
var lazy = this._lazyAddAttrs,
constr,
constrProto,
ci,
ei,
el,
classes = this._getClasses(),
attrCfgs = this._getAttrCfgs();
for (ci = classes.length-1; ci >= 0; ci--) {
constr = classes[ci];
constrProto = constr.prototype;
if (constr._yuibuild && constr._yuibuild.exts && !constr._yuibuild.dynamic) {
for (ei = 0, el = constr._yuibuild.exts.length; ei < el; ei++) {
constr._yuibuild.exts[ei].apply(this, arguments);
}
}
this.addAttrs(this._filterAttrCfgs(constr, attrCfgs), userVals, lazy);
if (constrProto.hasOwnProperty(INITIALIZER)) {
constrProto.initializer.apply(this, arguments);
}
}
},
/**
* Destroys the class hierarchy for this instance by invoking
* the descructor method on the prototype of each class in the hierarchy.
*
* @method _destroyHierarchy
* @private
*/
_destroyHierarchy : function() {
var constr,
constrProto,
ci, cl,
classes = this._getClasses();
for (ci = 0, cl = classes.length; ci < cl; ci++) {
constr = classes[ci];
constrProto = constr.prototype;
if (constrProto.hasOwnProperty(DESTRUCTOR)) {
constrProto.destructor.apply(this, arguments);
}
}
},
/**
* Default toString implementation. Provides the constructor NAME
* and the instance ID.
*
* @method toString
* @return {String} String representation for this object
*/
toString: function() {
return this.constructor.NAME + "[" + Y.stamp(this) + "]";
}
};
// Straightup augment, no wrapper functions
Y.mix(Base, Attribute, false, null, 1);
// Fix constructor
Base.prototype.constructor = Base;
Y.Base = Base;
// Fix constructor
Base.prototype.constructor = Base;
}, '3.0.0' ,{requires:['attribute-base']});
YUI.add('base-pluginhost', function(Y) {
/**
* The base-pluginhost submodule adds Plugin support to Base, by augmenting Base with
* Plugin.Host and setting up static (class level) Base.plug and Base.unplug methods.
*
* @module base
* @submodule base-pluginhost
* @for Base
*/
var Base = Y.Base,
PluginHost = Y.Plugin.Host;
Y.mix(Base, PluginHost, false, null, 1);
/**
* Alias for <a href="Plugin.Host.html#method_Plugin.Host.plug">Plugin.Host.plug</a>. See aliased
* method for argument and return value details.
*
* @method Base.plug
* @static
*/
Base.plug = PluginHost.plug;
/**
* Alias for <a href="Plugin.Host.html#method_Plugin.Host.unplug">Plugin.Host.unplug</a>. See the
* aliased method for argument and return value details.
*
* @method Base.unplug
* @static
*/
Base.unplug = PluginHost.unplug;
}, '3.0.0' ,{requires:['base-base', 'pluginhost']});
YUI.add('base-build', function(Y) {
/**
* The base-build submodule provides Base.build functionality, which
* can be used to create custom classes, by aggregating extensions onto
* a main class.
*
* @module base
* @submodule base-build
* @for Base
*/
var Base = Y.Base,
L = Y.Lang;
/**
* The build configuration for the Base class.
*
* Defines the static fields which need to be aggregated
* when the Base class is used as the main class passed to
* the <a href="#method_Base.build">Base.build</a> method.
*
* @property Base._buildCfg
* @type Object
* @static
* @final
* @private
*/
Base._buildCfg = {
aggregates : ["ATTRS", "_PLUG", "_UNPLUG"]
};
/**
* <p>
* Builds a custom constructor function (class) from the
* main function, and array of extension functions (classes)
* provided. The NAME field for the constructor function is
* defined by the first argument passed in.
* </p>
* <p>
* The cfg object supports the following properties
* </p>
* <dl>
* <dt>dynamic &#60;boolean&#62;</dt>
* <dd>
* <p>If true (default), a completely new class
* is created which extends the main class, and acts as the
* host on which the extension classes are augmented.</p>
* <p>If false, the extensions classes are augmented directly to
* the main class, modifying the main class' prototype.</p>
* </dd>
* <dt>aggregates &#60;String[]&#62;</dt>
* <dd>An array of static property names, which will get aggregated
* on to the built class, in addition to the default properties build
* will always aggregate as defined by the main class' static _buildCfg
* property.
* </dd>
* </dl>
*
* @method Base.build
* @static
* @param {Function} name The name of the new class. Used to defined the NAME property for the new class.
* @param {Function} main The main class on which to base the built class
* @param {Function[]} extensions The set of extension classes which will be
* augmented/aggregated to the built class.
* @param {Object} cfg Optional. Build configuration for the class (see description).
* @return {Function} A custom class, created from the provided main and extension classes
*/
Base.build = function(name, main, extensions, cfg) {
var build = Base.build,
builtClass = build._getClass(main, cfg),
aggregates = build._getAggregates(main, cfg),
dynamic = builtClass._yuibuild.dynamic,
i, l, val, extClass;
// Shallow isolate aggregates
if (dynamic) {
if (aggregates) {
for (i = 0, l = aggregates.length; i < l; ++i) {
val = aggregates[i];
if (main.hasOwnProperty(val)) {
builtClass[val] = L.isArray(main[val]) ? [] : {};
}
}
Y.aggregate(builtClass, main, true, aggregates);
}
}
// Augment/Aggregate
for (i = 0, l = extensions.length; i < l; i++) {
extClass = extensions[i];
if (aggregates) {
Y.aggregate(builtClass, extClass, true, aggregates);
}
// Old augment
Y.mix(builtClass, extClass, true, null, 1);
builtClass._yuibuild.exts.push(extClass);
}
builtClass.prototype.hasImpl = build._hasImpl;
if (dynamic) {
builtClass.NAME = name;
builtClass.prototype.constructor = builtClass;
}
return builtClass;
};
Y.mix(Base.build, {
_template: function(main) {
function BuiltClass() {
BuiltClass.superclass.constructor.apply(this, arguments);
var f = BuiltClass._yuibuild.exts,
l = f.length,
i;
for (i = 0; i < l; i++) {
f[i].apply(this, arguments);
}
return this;
}
Y.extend(BuiltClass, main);
return BuiltClass;
},
_hasImpl : function(extClass) {
var classes = this._getClasses();
for (var i = 0, l = classes.length; i < l; i++) {
var cls = classes[i];
if (cls._yuibuild) {
var exts = cls._yuibuild.exts,
ll = exts.length,
j;
for (j = 0; j < ll; j++) {
if (exts[j] === extClass) {
return true;
}
}
}
}
return false;
},
_getClass : function(main, cfg) {
var dynamic = (cfg && false === cfg.dynamic) ? false : true,
builtClass = (dynamic) ? Base.build._template(main) : main;
builtClass._yuibuild = {
id: null,
exts : [],
dynamic : dynamic
};
return builtClass;
},
_getAggregates : function(main, cfg) {
var aggr = [],
cfgAggr = (cfg && cfg.aggregates),
c = main,
classAggr;
while (c && c.prototype) {
classAggr = c._buildCfg && c._buildCfg.aggregates;
if (classAggr) {
aggr = aggr.concat(classAggr);
}
c = c.superclass ? c.superclass.constructor : null;
}
if (cfgAggr) {
aggr = aggr.concat(cfgAggr);
}
return aggr;
}
});
}, '3.0.0' ,{requires:['base-base']});
YUI.add('base', function(Y){}, '3.0.0' ,{use:['base-base', 'base-pluginhost', 'base-build']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("classnamemanager",function(C){var B="classNamePrefix",D="classNameDelimiter",A=C.config;A[B]=A[B]||"yui";A[D]=A[D]||"-";C.ClassNameManager=function(){var E=A[B],F=A[D];return{getClassName:C.cached(function(I,G){var H=E+F+((G)?Array.prototype.join.call(arguments,F):I);return H.replace(/\s/g,"");})};}();},"3.0.0");

View File

@@ -0,0 +1,87 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('classnamemanager', function(Y) {
/**
* Contains a singleton (ClassNameManager) that enables easy creation and caching of
* prefixed class names.
* @module classnamemanager
*/
/**
* A singleton class providing:
*
* <ul>
* <li>Easy creation of prefixed class names</li>
* <li>Caching of previously created class names for improved performance.</li>
* </ul>
*
* @class ClassNameManager
* @static
*/
// String constants
var CLASS_NAME_PREFIX = 'classNamePrefix',
CLASS_NAME_DELIMITER = 'classNameDelimiter',
CONFIG = Y.config;
// Global config
/**
* Configuration property indicating the prefix for all CSS class names in this YUI instance.
*
* @property Y.config.classNamePrefix
* @type {String}
* @default "yui"
* @static
*/
CONFIG[CLASS_NAME_PREFIX] = CONFIG[CLASS_NAME_PREFIX] || 'yui';
/**
* Configuration property indicating the delimiter used to compose all CSS class names in
* this YUI instance.
*
* @property Y.config.classNameDelimiter
* @type {String}
* @default "-"
* @static
*/
CONFIG[CLASS_NAME_DELIMITER] = CONFIG[CLASS_NAME_DELIMITER] || '-';
Y.ClassNameManager = function () {
var sPrefix = CONFIG[CLASS_NAME_PREFIX],
sDelimiter = CONFIG[CLASS_NAME_DELIMITER];
return {
/**
* Returns a class name prefixed with the the value of the
* <code>Y.config.classNamePrefix</code> attribute + the provided strings.
* Uses the <code>Y.config.classNameDelimiter</code> attribute to delimit the
* provided strings. E.g. Y.ClassNameManager.getClassName('foo','bar'); // yui-foo-bar
*
* @method getClassName
* @param {String}+ one or more classname bits to be joined and prefixed
*/
getClassName: Y.cached(function (c, x) {
var sClass = sPrefix + sDelimiter +
// ((x) ? Y.Array(arguments, 0, true).join(sDelimiter) : c);
((x) ? Array.prototype.join.call(arguments, sDelimiter) : c);
return sClass.replace(/\s/g, '');
})
};
}();
}, '3.0.0' );

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("collection",function(E){var C=E.Lang,D=Array.prototype,B=E.Array;B.lastIndexOf=(D.lastIndexOf)?function(A,F){return A.lastIndexOf(F);}:function(A,G){for(var F=A.length-1;F>=0;F=F-1){if(A[F]===G){break;}}return F;};B.unique=function(F,H){var A=F.slice(),G=0,J=-1,I=null;while(G<A.length){I=A[G];while((J=A.lastIndexOf(I))!==G){A.splice(J,1);}G+=1;}if(H){if(C.isNumber(A[0])){A.sort(B.numericSort);}else{A.sort();}}return A;};B.filter=(D.filter)?function(A,F,G){return D.filter.call(A,F,G);}:function(A,G,H){var F=[];B.each(A,function(K,J,I){if(G.call(H,K,J,I)){F.push(K);}});return F;};B.reject=function(A,F,G){return B.filter(A,function(J,I,H){return !F.call(G,J,I,H);});};B.every=(D.every)?function(A,F,G){return D.every.call(A,F,G);}:function(F,H,I){var A=F.length;for(var G=0;G<A;G=G+1){if(!H.call(I,F[G],G,F)){return false;}}return true;};B.map=(D.map)?function(A,F,G){return D.map.call(A,F,G);}:function(A,G,H){var F=[];B.each(A,function(K,J,I){F.push(G.call(H,K,J,I));});return F;};B.reduce=(D.reduce)?function(A,H,F,G){return D.reduce.call(A,function(L,K,J,I){return F.call(G,L,K,J,I);},H);}:function(A,I,G,H){var F=I;B.each(A,function(L,K,J){F=G.call(H,F,L,K,J);});return F;};B.find=function(F,H,I){var A=F.length;for(var G=0;G<A;G++){if(H.call(I,F[G],G,F)){return F[G];}}return null;};B.grep=function(A,F){return B.filter(A,function(H,G){return F.test(H);});};B.partition=function(A,G,H){var F={matches:[],rejects:[]};B.each(A,function(J,I){var K=G.call(H,J,I,A)?F.matches:F.rejects;K.push(J);});return F;};B.zip=function(F,A){var G=[];B.each(F,function(I,H){G.push([I,A[H]]);});return G;};},"3.0.0");

View File

@@ -0,0 +1,294 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('collection', function(Y) {
/**
* Collection utilities beyond what is provided in the YUI core
* @module collection
*/
var L = Y.Lang, Native = Array.prototype, A = Y.Array;
/**
* Adds the following array utilities to the YUI instance
* (Y.Array). This is in addition to the methods provided
* in the core.
* @class YUI~array~extras
*/
/**
* Returns the index of the last item in the array
* that contains the specified value, -1 if the
* value isn't found.
* method Array.lastIndexOf
* @static
* @param a {Array} the array to search
* @param val the value to search for
* @return {int} the index of hte item that contains the value or -1
*/
A.lastIndexOf = (Native.lastIndexOf) ?
function(a ,val) {
return a.lastIndexOf(val);
} :
function(a, val) {
for (var i=a.length-1; i>=0; i=i-1) {
if (a[i] === val) {
break;
}
}
return i;
};
/**
* Returns a copy of the array with the duplicate entries removed
* @method Array.unique
* @static
* @param a {Array} the array to find the subset of uniques for
* @param sort {bool} flag to denote if the array is sorted or not. Defaults to false, the more general operation
* @return {Array} a copy of the array with duplicate entries removed
*/
A.unique = function(a, sort) {
var b = a.slice(), i = 0, n = -1, item = null;
while (i < b.length) {
item = b[i];
while ((n = b.lastIndexOf(item)) !== i) {
b.splice(n, 1);
}
i += 1;
}
// Note: the sort option doesn't really belong here... I think it was added
// because there was a way to fast path the two operations together. That
// implementation was not working, so I replaced it with the following.
// Leaving it in so that the API doesn't get broken.
if (sort) {
if (L.isNumber(b[0])) {
b.sort(A.numericSort);
} else {
b.sort();
}
}
return b;
};
/**
* Executes the supplied function on each item in the array.
* Returns a new array containing the items that the supplied
* function returned true for.
* @method Array.filter
* @param a {Array} the array to iterate
* @param f {Function} the function to execute on each item
* @param o Optional context object
* @static
* @return {Array} The items on which the supplied function
* returned true. If no items matched an empty array is
* returned.
*/
A.filter = (Native.filter) ?
function(a, f, o) {
return Native.filter.call(a, f, o);
} :
function(a, f, o) {
var results = [];
A.each(a, function(item, i, a) {
if (f.call(o, item, i, a)) {
results.push(item);
}
});
return results;
};
/**
* The inverse of filter. Executes the supplied function on each item.
* Returns a new array containing the items that the supplied
* function returned *false* for.
* @method Array.reject
* @param a {Array} the array to iterate
* @param f {Function} the function to execute on each item
* @param o Optional context object
* @static
* @return {Array} The items on which the supplied function
* returned false.
*/
A.reject = function(a, f, o) {
return A.filter(a, function(item, i, a) {
return !f.call(o, item, i, a);
});
};
/**
* Executes the supplied function on each item in the array.
* @method Array.every
* @param a {Array} the array to iterate
* @param f {Function} the function to execute on each item
* @param o Optional context object
* @static
* @return {boolean} true if every item in the array returns true
* from the supplied function.
*/
A.every = (Native.every) ?
function(a, f, o) {
return Native.every.call(a,f,o);
} :
function(a, f, o) {
var l = a.length;
for (var i = 0; i < l; i=i+1) {
if (!f.call(o, a[i], i, a)) {
return false;
}
}
return true;
};
/**
* Executes the supplied function on each item in the array.
* @method Array.map
* @param a {Array} the array to iterate
* @param f {Function} the function to execute on each item
* @param o Optional context object
* @static
* @return {Array} A new array containing the return value
* of the supplied function for each item in the original
* array.
*/
A.map = (Native.map) ?
function(a, f, o) {
return Native.map.call(a, f, o);
} :
function(a, f, o) {
var results = [];
A.each(a, function(item, i, a) {
results.push(f.call(o, item, i, a));
});
return results;
};
/**
* Executes the supplied function on each item in the array.
* Reduce "folds" the array into a single value.
* @method Array.reduce
* @param a {Array} the array to iterate
* @param init The initial value to start from
* @param f {Function} the function to execute on each item. It
* is responsible for returning the updated value of the
* computation.
* @param o Optional context object
* @static
* @return A value that results from iteratively applying the
* supplied function to each element in the array.
*/
A.reduce = (Native.reduce) ?
function(a, init, f, o) {
//Firefox's Array.reduce does not allow inclusion of a
// thisObject, so we need to implement it manually
return Native.reduce.call(a, function(init, item, i, a) {
return f.call(o, init, item, i, a);
}, init);
} :
function(a, init, f, o) {
var r = init;
A.each(a, function (item, i, a) {
r = f.call(o, r, item, i, a);
});
return r;
};
/**
* Executes the supplied function on each item in the array,
* searching for the first item that matches the supplied
* function.
* @method Array.find
* @param a {Array} the array to search
* @param f {Function} the function to execute on each item.
* Iteration is stopped as soon as this function returns true
* on an item.
* @param o Optional context object
* @static
* @return {object} the first item that the supplied function
* returns true for, or null if it never returns true
*/
A.find = function(a, f, o) {
var l = a.length;
for(var i=0; i < l; i++) {
if (f.call(o, a[i], i, a)) {
return a[i];
}
}
return null;
};
/**
* Iterates over an array, returning a new array of all the elements
* that match the supplied regular expression
* @method Array.grep
* @param a {Array} a collection to iterate over
* @param pattern {RegExp} The regular expression to test against
* each item
* @static
* @return {Array} All the items in the collection that
* produce a match against the supplied regular expression.
* If no items match, an empty array is returned.
*/
A.grep = function (a, pattern) {
return A.filter(a, function (item, index) {
return pattern.test(item);
});
};
/**
* Partitions an array into two new arrays, one with the items
* that match the supplied function, and one with the items that
* do not.
* @method Array.partition
* @param a {Array} a collection to iterate over
* @paran f {Function} a function that will receive each item
* in the collection and its index.
* @param o Optional execution context of f.
* @static
* @return An object with two members, 'matches' and 'rejects',
* that are arrays containing the items that were selected or
* rejected by the test function (or an empty array).
*/
A.partition = function (a, f, o) {
var results = {matches: [], rejects: []};
A.each(a, function (item, index) {
var set = f.call(o, item, index, a) ? results.matches : results.rejects;
set.push(item);
});
return results;
};
/**
* Creates an array of arrays by pairing the corresponding
* elements of two arrays together into a new array.
* @method Array.zip
* @param a {Array} a collection to iterate over
* @param a2 {Array} another collection whose members will be
* paired with members of the first parameter
* @static
* @return An array of arrays formed by pairing each element
* of the first collection with an item in the second collection
* having the corresponding index.
*/
A.zip = function (a, a2) {
var results = [];
A.each(a, function (item, index) {
results.push([item, a2[index]]);
});
return results;
};
}, '3.0.0' );

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,896 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('compat', function(Y) {
var COMPAT_ARG = '~yui|2|compat~';
if (window.YAHOO != YUI) {
// get any existing YAHOO obj props
var o = (window.YAHOO) ? YUI.merge(window.YAHOO) : null;
// Make the YUI global the YAHOO global
window.YAHOO = YUI;
// augment old YAHOO props
if (o) {
Y.mix(Y, o);
}
}
// add old namespaces
Y.namespace("util", "widget", "example");
// case/location change
Y.env = (Y.env) ? Y.mix(Y.env, Y.Env) : Y.Env;
Y.lang = (Y.lang) ? Y.mix(Y.lang, Y.Lang) : Y.Lang;
Y.env.ua = Y.UA;
// support Y.register
Y.mix(Y.env, {
modules: [],
listeners: [],
getVersion: function(name) {
return this.Env.modules[name] || null;
}
});
var L = Y.lang;
// add old lang properties
Y.mix(L, {
augmentObject: function(r, s) {
var a = arguments, wl = (a.length > 2) ? Y.Array(a, 2, true) : null;
return Y.mix(r, s, (wl), wl);
},
augmentProto: function(r, s) {
var a = arguments, wl = (a.length > 2) ? Y.Array(a, 2, true) : null;
return Y.mix(r, s, (wl), wl, 1);
},
// extend: Y.bind(Y.extend, Y),
extend: Y.extend,
// merge: Y.bind(Y.merge, Y)
merge: Y.merge
}, true);
L.augment = L.augmentProto;
L.hasOwnProperty = function(o, k) {
return (o.hasOwnProperty(k));
};
Y.augmentProto = L.augmentProto;
// add register function
Y.mix(Y, {
register: function(name, mainClass, data) {
var mods = Y.Env.modules;
if (!mods[name]) {
mods[name] = { versions:[], builds:[] };
}
var m=mods[name],v=data.version,b=data.build,ls=Y.Env.listeners;
m.name = name;
m.version = v;
m.build = b;
m.versions.push(v);
m.builds.push(b);
m.mainClass = mainClass;
// fire the module load listeners
for (var i=0;i<ls.length;i=i+1) {
ls[i](m);
}
// label the main class
if (mainClass) {
mainClass.VERSION = v;
mainClass.BUILD = b;
} else {
}
}
});
// add old load listeners
if ("undefined" !== typeof YAHOO_config) {
var l=YAHOO_config.listener,ls=Y.Env.listeners,unique=true,i;
if (l) {
// if YAHOO is loaded multiple times we need to check to see if
// this is a new config object. If it is, add the new component
// load listener to the stack
for (i=0;i<ls.length;i=i+1) {
if (ls[i]==l) {
unique=false;
break;
}
}
if (unique) {
ls.push(l);
}
}
}
// add old registration for yahoo
Y.register("yahoo", Y, {version: "3.0.0", build: "1549"});
if (Y.Event) {
var o = {
/**
* Safari detection
* @property isSafari
* @private
* @static
* @deprecated use Y.Env.UA.webkit
*/
isSafari: Y.UA.webkit,
/**
* webkit version
* @property webkit
* @type string
* @private
* @static
* @deprecated use Y.Env.UA.webkit
*/
webkit: Y.UA.webkit,
/**
* Normalized keycodes for webkit/safari
* @property webkitKeymap
* @type {int: int}
* @private
* @static
* @final
*/
webkitKeymap: {
63232: 38, // up
63233: 40, // down
63234: 37, // left
63235: 39, // right
63276: 33, // page up
63277: 34, // page down
25: 9 // SHIFT-TAB (Safari provides a different key code in
// this case, even though the shiftKey modifier is set)
},
/**
* IE detection
* @property isIE
* @private
* @static
* @deprecated use Y.Env.UA.ie
*/
isIE: Y.UA.ie,
/**
* Returns scrollLeft
* @method _getScrollLeft
* @static
* @private
*/
_getScrollLeft: function() {
return this._getScroll()[1];
},
/**
* Returns scrollTop
* @method _getScrollTop
* @static
* @private
*/
_getScrollTop: function() {
return this._getScroll()[0];
},
/**
* Returns the scrollTop and scrollLeft. Used to calculate the
* pageX and pageY in Internet Explorer
* @method _getScroll
* @static
* @private
*/
_getScroll: function() {
var d = Y.config.doc, dd = d.documentElement, db = d.body;
if (dd && (dd.scrollTop || dd.scrollLeft)) {
return [dd.scrollTop, dd.scrollLeft];
} else if (db) {
return [db.scrollTop, db.scrollLeft];
} else {
return [0, 0];
}
},
/**
* Returns the event's pageX
* @method getPageX
* @param {Event} ev the event
* @return {int} the event's pageX
* @static
*/
getPageX: function(ev) {
var x = ev.pageX;
if (!x && 0 !== x) {
x = ev.clientX || 0;
if ( Y.UA.ie ) {
x += this._getScrollLeft();
}
}
return x;
},
/**
* Returns the charcode for an event
* @method getCharCode
* @param {Event} ev the event
* @return {int} the event's charCode
* @static
*/
getCharCode: function(ev) {
var code = ev.keyCode || ev.charCode || 0;
// webkit normalization
if (Y.UA.webkit && (code in Y.Event.webkitKeymap)) {
code = Y.Event.webkitKeymap[code];
}
return code;
},
/**
* Returns the event's pageY
* @method getPageY
* @param {Event} ev the event
* @return {int} the event's pageY
* @static
*/
getPageY: function(ev) {
var y = ev.pageY;
if (!y && 0 !== y) {
y = ev.clientY || 0;
if ( Y.UA.ie ) {
y += this._getScrollTop();
}
}
return y;
},
/**
* Returns the pageX and pageY properties as an indexed array.
* @method getXY
* @param {Event} ev the event
* @return {[x, y]} the pageX and pageY properties of the event
* @static
*/
getXY: function(ev) {
return [this.getPageX(ev), this.getPageY(ev)];
},
/**
* Returns the event's related target
* @method getRelatedTarget
* @param {Event} ev the event
* @return {HTMLElement} the event's relatedTarget
* @static
*/
getRelatedTarget: function(ev) {
var t = ev.relatedTarget;
if (!t) {
if (ev.type == "mouseout") {
t = ev.toElement;
} else if (ev.type == "mouseover") {
t = ev.fromElement;
}
}
return this.resolveTextNode(t);
},
/**
* Returns the time of the event. If the time is not included, the
* event is modified using the current time.
* @method getTime
* @param {Event} ev the event
* @return {Date} the time of the event
* @static
*/
getTime: function(ev) {
if (!ev.time) {
var t = new Date().getTime();
try {
ev.time = t;
} catch(ex) {
this.lastError = ex;
return t;
}
}
return ev.time;
},
/**
* Convenience method for stopPropagation + preventDefault
* @method stopEvent
* @param {Event} ev the event
* @static
*/
stopEvent: function(ev) {
this.stopPropagation(ev);
this.preventDefault(ev);
},
/**
* Stops event propagation
* @method stopPropagation
* @param {Event} ev the event
* @static
*/
stopPropagation: function(ev) {
if (ev.stopPropagation) {
ev.stopPropagation();
} else {
ev.cancelBubble = true;
}
},
/**
* Prevents the default behavior of the event
* @method preventDefault
* @param {Event} ev the event
* @static
*/
preventDefault: function(ev) {
if (ev.preventDefault) {
ev.preventDefault();
} else {
ev.returnValue = false;
}
},
/**
* Returns the event's target element. Safari sometimes provides
* a text node, and this is automatically resolved to the text
* node's parent so that it behaves like other browsers.
* @method getTarget
* @param {Event} ev the event
* @param {boolean} resolveTextNode when set to true the target's
* parent will be returned if the target is a
* text node. @deprecated, the text node is
* now resolved automatically
* @return {HTMLElement} the event's target
* @static
*/
getTarget: function(ev, resolveTextNode) {
var t = ev.target || ev.srcElement;
return this.resolveTextNode(t);
},
/**
* In some cases, some browsers will return a text node inside
* the actual element that was targeted. This normalizes the
* return value for getTarget and getRelatedTarget.
* @method resolveTextNode
* @param {HTMLElement} node node to resolve
* @return {HTMLElement} the normized node
* @static
*/
resolveTextNode: function(node) {
if (node && 3 == node.nodeType) {
return node.parentNode;
} else {
return node;
}
},
/**
* We cache elements bound by id because when the unload event
* fires, we can no longer use document.getElementById
* @method getEl
* @static
* @private
* @deprecated Elements are not cached any longer
*/
getEl: function(id) {
return Y.get(id);
}
};
Y.mix(Y.Event, o);
/**
* Calls Y.Event.attach with the correct argument order
* @method removeListener
*/
Y.Event.removeListener = function(el, type, fn, data, override) {
var context, a=[type, fn, el];
if (data) {
if (override) {
context = (override === true) ? data : override;
}
a.push(context);
a.push(data);
}
a.push(COMPAT_ARG);
return Y.Event.detach.apply(Y.Event, a);
};
/**
* Calls Y.Event.detach with the correct argument order
* @method addListener
*/
Y.Event.addListener = function(el, type, fn, data, override) {
// var a = Y.Array(arguments, 0, true), el = a.shift();
// a.splice(2, 0, el);
// return Y.Event.attach.apply(Y.Event, a);
var context, a=[type, fn, el];
if (data) {
if (override) {
context = (override === true) ? data : override;
}
a.push(context);
a.push(data);
}
a.push(COMPAT_ARG);
return Y.Event.attach.apply(Y.Event, a);
};
Y.Event.on = Y.Event.addListener;
var newOnavail = Y.Event.onAvailable;
Y.Event.onAvailable = function(id, fn, p_obj, p_override) {
return newOnavail(id, fn, p_obj, p_override, false, true);
};
Y.Event.onContentReady = function(id, fn, p_obj, p_override) {
return newOnavail(id, fn, p_obj, p_override, true, true);
};
Y.Event.onDOMReady = function(fn) {
var a = Y.Array(arguments, 0, true);
a.unshift('event:ready');
return Y.on.apply(Y, a);
};
Y.util.Event = Y.Event;
var CE = function(type, oScope, silent, signature) {
//debugger;
var o = {
context: oScope,
silent: silent || false
// signature: signature || CE.LIST
};
CE.superclass.constructor.call(this, type, o);
this.signature = signature || CE.LIST;
};
Y.extend(CE, Y.CustomEvent, {
});
/**
* Subscriber listener sigature constant. The LIST type returns three
* parameters: the event type, the array of args passed to fire, and
* the optional custom object
* @property YAHOO.util.CustomEvent.LIST
* @static
* @type int
*/
CE.LIST = 0;
/**
* Subscriber listener sigature constant. The FLAT type returns two
* parameters: the first argument passed to fire and the optional
* custom object
* @property YAHOO.util.CustomEvent.FLAT
* @static
* @type int
*/
CE.FLAT = 1;
Y.util.CustomEvent = CE;
var EP = function() {
//console.log('Compat CustomEvent constructor executed: ' + this._yuid);
if (!this._yuievt) {
var sub = this.subscribe;
Y.EventTarget.apply(this, arguments);
this.subscribe = sub;
this.__yuiepinit = function() {};
}
};
Y.extend(EP, Y.EventTarget, {
createEvent: function(type, o) {
o = o || {};
o.signature = o.signature || CE.FLAT;
return this.publish(type, o);
},
subscribe: function(type, fn, obj, override) {
var ce = this._yuievt.events[type] || this.createEvent(type),
a = Y.Array(arguments);
if (override && true !== override) {
// a[2] = override;
// a[1] = obj;
}
Y.EventTarget.prototype.subscribe.apply(this, a);
},
fireEvent: function(type) {
return this.fire.apply(this, arguments);
},
hasEvent: function(type) {
return this.getEvent(type);
}
});
Y.util.EventProvider = EP;
}
Y.register("event", Y, {version: "3.0.0", build: "1549"});
var propertyCache = {};
var patterns = {
HYPHEN: /(-[a-z])/i, // to normalize get/setStyle
ROOT_TAG: /^body|html$/i, // body for quirks mode, html for standards,
OP_SCROLL:/^(?:inline|table-row)$/i
};
var hyphenToCamel = function(property) {
if ( !patterns.HYPHEN.test(property) ) {
return property; // no hyphens
}
if (propertyCache[property]) { // already converted
return propertyCache[property];
}
var converted = property;
while( patterns.HYPHEN.exec(converted) ) {
converted = converted.replace(RegExp.$1,
RegExp.$1.substr(1).toUpperCase());
}
propertyCache[property] = converted;
return converted;
//return property.replace(/-([a-z])/gi, function(m0, m1) {return m1.toUpperCase()}) // cant use function as 2nd arg yet due to safari bug
};
var Dom = {
get: function(el) {
if (el) {
if (el.nodeType || el.item) { // Node, or NodeList
return el;
}
if (typeof el === 'string') { // id
return document.getElementById(el);
}
if ('length' in el) { // array-like
var c = [];
for (var i = 0, len = el.length; i < len; ++i) {
c[c.length] = Dom.get(el[i]);
}
return c;
}
return el; // some other object, just pass it back
}
return null;
},
isAncestor: function(haystack, needle) {
return YUI.DOM.contains(Dom.get(haystack), Dom.get(needle));
},
inDocument: function(el) {
return Dom.isAncestor(Y.config.doc.documentElement, el);
},
batch: function(el, method, o, override, args) {
el = (el && (el.tagName || el.item)) ? el : Dom.get(el); // skip get() when possible
if (!el || !method) {
return false;
}
if (args) {
args = Y.Array(args);
}
var scope = (override) ? o : window;
var apply = function(el) {
if (args) {
var tmp = slice.call(args);
tmp.unshift(el);
return method.apply(scope, tmp);
} else {
return method.call(scope, el, o);
}
};
if (el.tagName || el.length === undefined) { // element or not array-like
return apply(el);
}
var collection = [];
for (var i = 0, len = el.length; i < len; ++i) {
collection[collection.length] = apply(el[i]);
}
return collection;
},
// 2.x returns false if already present
_addClass: function(el, className) {
if ( YUI.DOM.hasClass(el, className) ) {
return false;
}
YUI.DOM.addClass(el, className);
return true;
},
// 2.x returns false if not present
_removeClass: function(el, className) {
if ( !YUI.DOM.hasClass(el, className) ) {
return false;
}
YUI.DOM.removeClass(el, className);
return true;
},
// 2.x returns false if no newClass or same as oldClass
_replaceClass: function(el, oldClass, newClass) {
if (!newClass || oldClass === newClass) {
return false;
}
YUI.DOM.replaceClass(el, oldClass, newClass);
return true;
},
getElementsByClassName: function(className, tag, root) {
tag = tag || '*';
root = (root) ? Dom.get(root) : Y.config.doc;
var nodes = [];
if (root) {
nodes = Y.Selector.query(tag + '.' + className, root);
}
return nodes;
},
getElementsBy: function(method, tag, root) {
tag = tag || '*';
root = (root) ? Dom.get(root) : null || document;
var nodes = [];
if (root) {
nodes = YUI.DOM.byTag(tag, root, method);
}
return nodes;
},
getViewportWidth: YUI.DOM.winWidth,
getViewportHeight: YUI.DOM.winHeight,
getDocumentWidth: YUI.DOM.docWidth,
getDocumentHeight: YUI.DOM.docHeight,
getDocumentScrollTop: YUI.DOM.docScrollY,
getDocumentScrollLeft: YUI.DOM.docScrollX,
getDocumentHeight: YUI.DOM.docHeight,
_guid: function(el, prefix) {
prefix = prefix || 'yui-gen';
Dom._id_counter = Dom._id_counter || 0;
if (el && el.id) { // do not override existing ID
return el.id;
}
var id = prefix + Dom._id_counter++;
if (el) {
el.id = id;
}
return id;
},
_region: function(el) {
if ( (el.parentNode === null || el.offsetParent === null ||
YUI.DOM.getStyle(el, 'display') == 'none') && el != el.ownerDocument.body) {
return false;
}
return YUI.DOM.region(el);
},
_ancestorByClass: function(element, className) {
return YUI.DOM.ancestor(element, function(el) {
return YUI.DOM.hasClass(el, className);
});
},
_ancestorByTag: function(element, tag) {
tag = tag.toUpperCase();
return YUI.DOM.ancestor(element, function(el) {
return el.tagName.toUpperCase() === tag;
});
}
};
var slice = [].slice;
var wrap = function(fn, name) {
Dom[name] = function() {
var args = slice.call(arguments);
args[0] = Dom.get(args[0]);
return fn.apply(Dom, args);
};
};
var wrapped = {
getAncestorBy: YUI.DOM.ancestor,
getAncestorByClassName: Dom._ancestorByClass,
getAncestorByTagName: Dom._ancestorByTag,
getPreviousSiblingBy: YUI.DOM.previous,
getPreviousSibling: YUI.DOM.previous,
getNextSiblingBy: YUI.DOM.next,
getNextSibling: YUI.DOM.next,
getFirstChildBy: YUI.DOM.firstChild,
getFirstChild: YUI.DOM.firstChild,
getLastChildBy: YUI.DOM.lastChild,
getLastChild: YUI.DOM.lastChild,
getChildrenBy: YUI.DOM.children,
getChildren: YUI.DOM.children,
insertBefore: function(newNode, refNode) {
YUI.DOM.insertBefore(Dom.get(newNode), Dom.get(refNode));
},
insertAfter: function(newNode, refNode) {
YUI.DOM.insertAfter(Dom.get(newNode), Dom.get(refNode));
}
};
Y.each(wrapped, wrap);
var batched = {
getStyle: YUI.DOM.getStyle,
setStyle: YUI.DOM.setStyle,
getXY: YUI.DOM.getXY,
setXY: YUI.DOM.setXY,
getX: YUI.DOM.getX,
getY: YUI.DOM.getY,
setX: YUI.DOM.setX,
setY: YUI.DOM.setY,
getRegion: Dom._region,
hasClass: YUI.DOM.hasClass,
addClass: Dom._addClass,
removeClass: Dom._removeClass,
replaceClass: Dom._replaceClass,
generateId: Dom._guid
};
Y.each(batched, function(v, n) {
Dom[n] = function(el) {
var args = slice.call(arguments, 1);
return Dom.batch(el, v, null, null, args);
};
});
Y.util.Dom = Dom;
YAHOO.util.Region = function(t, r, b, l) {
this.top = t;
this[1] = t;
this.right = r;
this.bottom = b;
this.left = l;
this[0] = l;
};
YAHOO.util.Region.prototype.contains = function(region) {
return ( region.left >= this.left &&
region.right <= this.right &&
region.top >= this.top &&
region.bottom <= this.bottom );
};
YAHOO.util.Region.prototype.getArea = function() {
return ( (this.bottom - this.top) * (this.right - this.left) );
};
YAHOO.util.Region.prototype.intersect = function(region) {
var t = Math.max( this.top, region.top );
var r = Math.min( this.right, region.right );
var b = Math.min( this.bottom, region.bottom );
var l = Math.max( this.left, region.left );
if (b >= t && r >= l) {
return new YAHOO.util.Region(t, r, b, l);
} else {
return null;
}
};
YAHOO.util.Region.prototype.union = function(region) {
var t = Math.min( this.top, region.top );
var r = Math.max( this.right, region.right );
var b = Math.max( this.bottom, region.bottom );
var l = Math.min( this.left, region.left );
return new YAHOO.util.Region(t, r, b, l);
};
YAHOO.util.Region.prototype.toString = function() {
return ( "Region {" +
"top: " + this.top +
", right: " + this.right +
", bottom: " + this.bottom +
", left: " + this.left +
"}" );
};
YAHOO.util.Region.getRegion = function(el) {
return YUI.DOM.region(el);
};
YAHOO.util.Point = function(x, y) {
if (YAHOO.lang.isArray(x)) { // accept input from Dom.getXY, Event.getXY, etc.
y = x[1]; // dont blow away x yet
x = x[0];
}
this.x = this.right = this.left = this[0] = x;
this.y = this.top = this.bottom = this[1] = y;
};
YAHOO.util.Point.prototype = new YAHOO.util.Region();
}, '3.0.0' ,{requires:['dom','event']});
YUI._setup(); YUI.use('dom', 'event', 'compat');

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,710 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('console-filters', function(Y) {
/**
* <p>Provides Plugin.ConsoleFilters plugin class.</p>
*
* <p>This plugin adds the ability to control which Console entries display by filtering on category and source. Two groups of checkboxes are added to the Console footer, one for categories and the other for sources. Only those messages that match a checked category or source are displayed.</p>
*
* @module console-filters
* @namespace Plugin
* @class ConsoleFilters
*/
// Some common strings and functions
var getCN = Y.ClassNameManager.getClassName,
CONSOLE = 'console',
FILTERS = 'filters',
FILTER = 'filter',
CATEGORY = 'category',
SOURCE = 'source',
CATEGORY_DOT = 'category.',
SOURCE_DOT = 'source.',
HOST = 'host',
PARENT_NODE = 'parentNode',
CHECKED = 'checked',
DEF_VISIBILITY = 'defaultVisibility',
DOT = '.',
EMPTY = '',
C_BODY = DOT + Y.Console.CHROME_CLASSES.console_bd_class,
C_FOOT = DOT + Y.Console.CHROME_CLASSES.console_ft_class,
SEL_CHECK = 'input[type=checkbox].',
isString = Y.Lang.isString;
function ConsoleFilters() {
ConsoleFilters.superclass.constructor.apply(this,arguments);
}
Y.mix(ConsoleFilters,{
/**
* Plugin name.
*
* @property ConsoleFilters.NAME
* @type String
* @static
* @default 'consoleFilters'
*/
NAME : 'consoleFilters',
/**
* The namespace hung off the host object that this plugin will inhabit.
*
* @property ConsoleFilters.NS
* @type String
* @static
* @default 'filter'
*/
NS : FILTER,
/**
* Markup template used to create the container for the category filters.
*
* @property ConsoleFilters.CATEGORIES_TEMPLATE
* @type String
* @static
*/
CATEGORIES_TEMPLATE :
'<div class="{categories}"></div>',
/**
* Markup template used to create the container for the source filters.
*
* @property ConsoleFilters.SOURCES_TEMPLATE
* @type String
* @static
*/
SOURCES_TEMPLATE :
'<div class="{sources}"></div>',
/**
* Markup template used to create the category and source filter checkboxes.
*
* @property ConsoleFilters.FILTER_TEMPLATE
* @type String
* @static
*/
FILTER_TEMPLATE :
// IE8 and FF3 don't permit breaking _between_ nowrap elements. IE8
// doesn't understand (non spec) wbr tag, nor does it create text nodes
// for spaces in innerHTML strings. The thin-space entity suffices to
// create a breakable point.
'<label class="{filter_label}">'+
'<input type="checkbox" value="{filter_name}" '+
'class="{filter} {filter_class}"> {filter_name}'+
'</label>&#8201;',
/**
* Classnames used by the templates when creating nodes.
*
* @property ConsoleFilters.CHROME_CLASSES
* @type Object
* @static
* @protected
*/
CHROME_CLASSES : {
categories : getCN(CONSOLE,FILTERS,'categories'),
sources : getCN(CONSOLE,FILTERS,'sources'),
category : getCN(CONSOLE,FILTER,CATEGORY),
source : getCN(CONSOLE,FILTER,SOURCE),
filter : getCN(CONSOLE,FILTER),
filter_label : getCN(CONSOLE,FILTER,'label')
},
ATTRS : {
/**
* Default visibility applied to new categories and sources.
*
* @attribute defaultVisibility
* @type {Boolean}
* @default true
*/
defaultVisibility : {
value : true,
validator : Y.Lang.isBoolean
},
/**
* <p>Map of entry categories to their visibility status. Update a
* particular category's visibility by setting the subattribute to true
* (visible) or false (hidden).</p>
*
* <p>For example, yconsole.filter.set('category.info', false) to hide
* log entries with the category/logLevel of 'info'.</p>
*
* <p>Similarly, yconsole.filter.get('category.warn') will return a
* boolean indicating whether that category is currently being included
* in the UI.</p>
*
* <p>Unlike the YUI instance configuration's logInclude and logExclude
* properties, filtered entries are only hidden from the UI, but
* can be made visible again.</p>
*
* @attribute category
* @type Object
*/
category : {
value : {},
validator : function (v,k) {
return this._validateCategory(k,v);
}
},
/**
* <p>Map of entry sources to their visibility status. Update a
* particular sources's visibility by setting the subattribute to true
* (visible) or false (hidden).</p>
*
* <p>For example, yconsole.filter.set('sources.slider', false) to hide
* log entries originating from Y.Slider.</p>
*
* @attribute source
* @type Object
*/
source : {
value : {},
validator : function (v,k) {
return this._validateSource(k,v);
}
},
/**
* Maximum number of entries to store in the message cache. Use this to
* limit the memory footprint in environments with heavy log usage.
* By default, there is no limit (Number.POSITIVE_INFINITY).
*
* @attribute cacheLimit
* @type {Number}
* @default Number.POSITIVE_INFINITY
*/
cacheLimit : {
value : Number.POSITIVE_INFINITY,
setter : function (v) {
if (Y.Lang.isNumber(v)) {
this._cacheLimit = v;
return v;
} else {
return Y.Attribute.INVALID_VALUE;
}
}
}
}
});
Y.extend(ConsoleFilters, Y.Plugin.Base, {
/**
* Collection of all log messages passed through since the plugin's
* instantiation. This holds all messages regardless of filter status.
* Used as a single source of truth for repopulating the Console body when
* filters are changed.
*
* @property _entries
* @type Array
* @protected
*/
_entries : null,
_cacheLimit : Number.POSITIVE_INFINITY,
/**
* The container node created to house the category filters.
*
* @property _categories
* @type Node
* @protected
*/
_categories : null,
/**
* The container node created to house the source filters.
*
* @property _sources
* @type Node
* @protected
*/
_sources : null,
/**
* Initialize entries collection and attach listeners to host events and
* methods.
*
* @method initializer
* @protected
*/
initializer : function () {
this._entries = [];
this.get(HOST).on("entry", this._onEntry, this);
this.doAfter("renderUI", this.renderUI);
this.doAfter("syncUI", this.syncUI);
this.doAfter("bindUI", this.bindUI);
this.doAfter("clearConsole", this._afterClearConsole);
if (this.get(HOST).get('rendered')) {
this.renderUI();
this.syncUI();
this.bindUI();
}
this.after("cacheLimitChange", this._afterCacheLimitChange);
},
/**
* Removes the plugin UI and unwires events.
*
* @method destructor
* @protected
*/
destructor : function () {
//TODO: grab last {consoleLimit} entries and update the console with
//them (no filtering)
this._entries = [];
if (this._categories) {
this._categories.get(PARENT_NODE).removeChild(this._categories);
}
if (this._sources) {
this._sources.get(PARENT_NODE).removeChild(this._sources);
}
},
/**
* Adds the category and source filter sections to the Console footer.
*
* @method renderUI
* @protected
*/
renderUI : function () {
var foot = this.get(HOST).get('contentBox').query(C_FOOT),
html;
if (foot) {
html = Y.substitute(
ConsoleFilters.CATEGORIES_TEMPLATE,
ConsoleFilters.CHROME_CLASSES);
this._categories = foot.appendChild(Y.Node.create(html));
html = Y.substitute(
ConsoleFilters.SOURCES_TEMPLATE,
ConsoleFilters.CHROME_CLASSES);
this._sources = foot.appendChild(Y.Node.create(html));
}
},
/**
* Binds to checkbox click events and internal attribute change events to
* maintain the UI state.
*
* @method bindUI
* @protected
*/
bindUI : function () {
this._categories.on('click', Y.bind(this._onCategoryCheckboxClick, this));
this._sources.on('click', Y.bind(this._onSourceCheckboxClick, this));
this.after('categoryChange',this._afterCategoryChange);
this.after('sourceChange', this._afterSourceChange);
},
/**
* Updates the UI to be in accordance with the current state of the plugin.
*
* @method syncUI
*/
syncUI : function () {
Y.each(this.get(CATEGORY), function (v, k) {
this._uiSetCheckbox(CATEGORY, k, v);
}, this);
Y.each(this.get(SOURCE), function (v, k) {
this._uiSetCheckbox(SOURCE, k, v);
}, this);
this.refreshConsole();
},
/**
* Ensures a filter is set up for any new categories or sources and
* collects the messages in _entries. If the message is stamped with a
* category or source that is currently being filtered out, the message
* will not pass to the Console's print buffer.
*
* @method _onEntry
* @param e {Event} the custom event object
* @protected
*/
_onEntry : function (e) {
this._entries.push(e.message);
var cat = CATEGORY_DOT + e.message.category,
src = SOURCE_DOT + e.message.source,
cat_filter = this.get(cat),
src_filter = this.get(src),
overLimit = this._entries.length - this._cacheLimit,
visible;
if (overLimit > 0) {
this._entries.splice(0, overLimit);
}
if (cat_filter === undefined) {
visible = this.get(DEF_VISIBILITY);
this.set(cat, visible);
cat_filter = visible;
}
if (src_filter === undefined) {
visible = this.get(DEF_VISIBILITY);
this.set(src, visible);
src_filter = visible;
}
if (!cat_filter || !src_filter) {
e.preventDefault();
}
},
/**
* Flushes the cached entries after a call to the Console's clearConsole().
*
* @method _afterClearConsole
* @protected
*/
_afterClearConsole : function () {
this._entries = [];
},
/**
* Triggers the Console to update if a known category filter
* changes value (e.g. visible => hidden). Updates the appropriate
* checkbox's checked state if necessary.
*
* @method _afterCategoryChange
* @param e {Event} the attribute change event object
* @protected
*/
_afterCategoryChange : function (e) {
var cat = e.subAttrName.replace(/category\./, EMPTY),
before = e.prevVal,
after = e.newVal;
// Don't update the console for new categories
if (!cat || before[cat] !== undefined) {
this.refreshConsole();
this._filterBuffer();
}
if (cat && !e.fromUI) {
this._uiSetCheckbox(CATEGORY, cat, after[cat]);
}
},
/**
* Triggers the Console to update if a known source filter
* changes value (e.g. visible => hidden). Updates the appropriate
* checkbox's checked state if necessary.
*
* @method _afterSourceChange
* @param e {Event} the attribute change event object
* @protected
*/
_afterSourceChange : function (e) {
var src = e.subAttrName.replace(/source\./, EMPTY),
before = e.prevVal,
after = e.newVal;
// Don't update the console for new sources
if (!src || before[src] !== undefined) {
this.refreshConsole();
this._filterBuffer();
}
if (src && !e.fromUI) {
this._uiSetCheckbox(SOURCE, src, after[src]);
}
},
/**
* Flushes the Console's print buffer of any entries that have a category
* or source that is currently being excluded.
*
* @method _filterBuffer
* @protected
*/
_filterBuffer : function () {
var cats = this.get(CATEGORY),
srcs = this.get(SOURCE),
buffer = this.get(HOST).buffer,
start = null,
i;
for (i = buffer.length - 1; i >= 0; --i) {
if (!cats[buffer[i].category] || !srcs[buffer[i].source]) {
start = start || i;
} else if (start) {
buffer.splice(i,(start - i));
start = null;
}
}
if (start) {
buffer.splice(0,start + 1);
}
},
/**
* Trims the cache of entries to the appropriate new length.
*
* @method _afterCacheLimitChange
* @param e {Event} the attribute change event object
* @protected
*/
_afterCacheLimitChange : function (e) {
if (isFinite(e.newVal)) {
var delta = this._entries.length - e.newVal;
if (delta > 0) {
this._entries.splice(0,delta);
}
}
},
/**
* Repopulates the Console with entries appropriate to the current filter
* settings.
*
* @method refreshConsole
*/
refreshConsole : function () {
var entries = this._entries,
host = this.get(HOST),
body = host.get('contentBox').query(C_BODY),
remaining = host.get('consoleLimit'),
cats = this.get(CATEGORY),
srcs = this.get(SOURCE),
buffer = [],
i,e;
if (body) {
host._cancelPrintLoop();
// Evaluate all entries from latest to oldest
for (i = entries.length - 1; i >= 0 && remaining >= 0; --i) {
e = entries[i];
if (cats[e.category] && srcs[e.source]) {
buffer.unshift(e);
--remaining;
}
}
body.set('innerHTML',EMPTY);
host.buffer = buffer;
host.printBuffer();
}
},
/**
* Updates the checked property of a filter checkbox of the specified type.
* If no checkbox is found for the input params, one is created.
*
* @method _uiSetCheckbox
* @param type {String} 'category' or 'source'
* @param item {String} the name of the filter (e.g. 'info', 'event')
* @param checked {Boolean} value to set the checkbox's checked property
* @protected
*/
_uiSetCheckbox : function (type, item, checked) {
if (type && item) {
var container = type === CATEGORY ?
this._categories :
this._sources,
sel = SEL_CHECK + getCN(CONSOLE,FILTER,item),
checkbox = container.query(sel),
host;
if (!checkbox) {
host = this.get(HOST);
this._createCheckbox(container, item);
checkbox = container.query(sel);
host._uiSetHeight(host.get('height'));
}
checkbox.set(CHECKED, checked);
}
},
/**
* Passes checkbox clicks on to the category attribute.
*
* @method _onCategoryCheckboxClick
* @param e {Event} the DOM event
* @protected
*/
_onCategoryCheckboxClick : function (e) {
var t = e.target, cat;
if (t.hasClass(ConsoleFilters.CHROME_CLASSES.filter)) {
cat = t.get('value');
if (cat && cat in this.get(CATEGORY)) {
this.set(CATEGORY_DOT + cat, t.get(CHECKED), { fromUI: true });
}
}
},
/**
* Passes checkbox clicks on to the source attribute.
*
* @method _onSourceCheckboxClick
* @param e {Event} the DOM event
* @protected
*/
_onSourceCheckboxClick : function (e) {
var t = e.target, src;
if (t.hasClass(ConsoleFilters.CHROME_CLASSES.filter)) {
src = t.get('value');
if (src && src in this.get(SOURCE)) {
this.set(SOURCE_DOT + src, t.get(CHECKED), { fromUI: true });
}
}
},
/**
* Hides any number of categories from the UI. Convenience method for
* myConsole.filter.set('category.foo', false); set('category.bar', false);
* and so on.
*
* @method hideCategory
* @param cat* {String} 1..n categories to filter out of the UI
*/
hideCategory : function (cat, multiple) {
if (isString(multiple)) {
Y.Array.each(arguments, arguments.callee, this);
} else {
this.set(CATEGORY_DOT + cat, false);
}
},
/**
* Shows any number of categories in the UI. Convenience method for
* myConsole.filter.set('category.foo', true); set('category.bar', true);
* and so on.
*
* @method showCategory
* @param cat* {String} 1..n categories to allow to display in the UI
*/
showCategory : function (cat, multiple) {
if (isString(multiple)) {
Y.Array.each(arguments, arguments.callee, this);
} else {
this.set(CATEGORY_DOT + cat, true);
}
},
/**
* Hides any number of sources from the UI. Convenience method for
* myConsole.filter.set('source.foo', false); set('source.bar', false);
* and so on.
*
* @method hideSource
* @param src* {String} 1..n sources to filter out of the UI
*/
hideSource : function (src, multiple) {
if (isString(multiple)) {
Y.Array.each(arguments, arguments.callee, this);
} else {
this.set(SOURCE_DOT + src, false);
}
},
/**
* Shows any number of sources in the UI. Convenience method for
* myConsole.filter.set('source.foo', true); set('source.bar', true);
* and so on.
*
* @method showSource
* @param src* {String} 1..n sources to allow to display in the UI
*/
showSource : function (src, multiple) {
if (isString(multiple)) {
Y.Array.each(arguments, arguments.callee, this);
} else {
this.set(SOURCE_DOT + src, true);
}
},
/**
* Creates a checkbox and label from the ConsoleFilters.FILTER_TEMPLATE for
* the provided type and name. The checkbox and label are appended to the
* container node passes as the first arg.
*
* @method _createCheckbox
* @param container {Node} the parentNode of the new checkbox and label
* @param name {String} the identifier of the filter
* @protected
*/
_createCheckbox : function (container, name) {
var info = Y.merge(ConsoleFilters.CHROME_CLASSES, {
filter_name : name,
filter_class : getCN(CONSOLE, FILTER, name)
}),
node = Y.Node.create(
Y.substitute(ConsoleFilters.FILTER_TEMPLATE, info));
container.appendChild(node);
},
/**
* Validates category updates are objects and the subattribute is not too
* deep.
*
* @method _validateCategory
* @param cat {String} the new category:visibility map
* @param v {String} the subattribute path updated
* @return Boolean
* @protected
*/
_validateCategory : function (cat, v) {
return Y.Lang.isObject(v,true) && cat.split(/\./).length < 3;
},
/**
* Validates source updates are objects and the subattribute is not too
* deep.
*
* @method _validateSource
* @param cat {String} the new source:visibility map
* @param v {String} the subattribute path updated
* @return Boolean
* @protected
*/
_validateSource : function (src, v) {
return Y.Lang.isObject(v,true) && src.split(/\./).length < 3;
}
});
Y.namespace('Plugin').ConsoleFilters = ConsoleFilters;
}, '3.0.0' ,{requires:['console','plugin']});

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("cookie",function(C){var K=C.Lang,I=C.Object,G=null,D=K.isString,P=K.isObject,F=K.isUndefined,E=K.isFunction,H=encodeURIComponent,B=decodeURIComponent,N=C.config.doc;function J(L){throw new TypeError(L);}function M(L){if(!D(L)||L===""){J("Cookie name must be a non-empty string.");}}function A(L){if(!D(L)||L===""){J("Subcookie name must be a non-empty string.");}}C.Cookie={_createCookieString:function(Q,T,R,O){O=O||{};var V=H(Q)+"="+(R?H(T):T),L=O.expires,U=O.path,S=O.domain;if(P(O)){if(L instanceof Date){V+="; expires="+L.toUTCString();}if(D(U)&&U!==""){V+="; path="+U;}if(D(S)&&S!==""){V+="; domain="+S;}if(O.secure===true){V+="; secure";}}return V;},_createCookieHashString:function(L){if(!P(L)){J("Cookie._createCookieHashString(): Argument must be an object.");}var O=[];I.each(L,function(R,Q){if(!E(R)&&!F(R)){O.push(H(Q)+"="+H(String(R)));}});return O.join("&");},_parseCookieHash:function(S){var R=S.split("&"),T=G,Q={};if(S.length){for(var O=0,L=R.length;O<L;O++){T=R[O].split("=");Q[B(T[0])]=B(T[1]);}}return Q;},_parseCookieString:function(W,Y){var X={};if(D(W)&&W.length>0){var L=(Y===false?function(Z){return Z;}:B),U=W.split(/;\s/g),V=G,O=G,R=G;for(var Q=0,S=U.length;Q<S;Q++){R=U[Q].match(/([^=]+)=/i);if(R instanceof Array){try{V=B(R[1]);O=L(U[Q].substring(R[1].length+1));}catch(T){}}else{V=B(U[Q]);O="";}X[V]=O;}}return X;},exists:function(L){M(L);var O=this._parseCookieString(N.cookie,true);return O.hasOwnProperty(L);},get:function(O,L){M(O);var S,Q,R;if(E(L)){R=L;L={};}else{if(P(L)){R=L.converter;}else{L={};}}S=this._parseCookieString(N.cookie,!L.raw);Q=S[O];if(F(Q)){return G;}if(!E(R)){return Q;}else{return R(Q);}},getSub:function(L,Q,O){var R=this.getSubs(L);if(R!==G){A(Q);if(F(R[Q])){return G;}if(!E(O)){return R[Q];}else{return O(R[Q]);}}else{return G;}},getSubs:function(L){M(L);var O=this._parseCookieString(N.cookie,false);if(D(O[L])){return this._parseCookieHash(O[L]);}return G;},remove:function(O,L){M(O);L=C.merge(L||{},{expires:new Date(0)});return this.set(O,"",L);},removeSub:function(O,S,L){M(O);A(S);L=L||{};var R=this.getSubs(O);if(P(R)&&R.hasOwnProperty(S)){delete R[S];if(!L.removeIfEmpty){return this.setSubs(O,R,L);}else{for(var Q in R){if(R.hasOwnProperty(Q)&&!E(R[Q])&&!F(R[Q])){return this.setSubs(O,R,L);}}return this.remove(O,L);}}else{return"";}},set:function(O,Q,L){M(O);if(F(Q)){J("Cookie.set(): Value cannot be undefined.");}L=L||{};var R=this._createCookieString(O,Q,!L.raw,L);N.cookie=R;return R;},setSub:function(O,R,Q,L){M(O);A(R);if(F(Q)){J("Cookie.setSub(): Subcookie value cannot be undefined.");}var S=this.getSubs(O);if(!P(S)){S={};}S[R]=Q;return this.setSubs(O,S,L);},setSubs:function(O,Q,L){M(O);if(!P(Q)){J("Cookie.setSubs(): Cookie value must be an object.");}var R=this._createCookieString(O,this._createCookieHashString(Q),false,L);N.cookie=R;return R;}};},"3.0.0",{requires:["yui-base"]});

View File

@@ -0,0 +1,491 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('cookie', function(Y) {
/**
* Utilities for cookie management
* @module cookie
*/
//shortcuts
var L = Y.Lang,
O = Y.Object,
NULL = null,
//shortcuts to functions
isString = L.isString,
isObject = L.isObject,
isUndefined = L.isUndefined,
isFunction = L.isFunction,
encode = encodeURIComponent,
decode = decodeURIComponent,
//shortcut to document
doc = Y.config.doc;
/*
* Throws an error message.
*/
function error(message){
throw new TypeError(message);
}
/*
* Checks the validity of a cookie name.
*/
function validateCookieName(name){
if (!isString(name) || name === ""){
error("Cookie name must be a non-empty string.");
}
}
/*
* Checks the validity of a subcookie name.
*/
function validateSubcookieName(subName){
if (!isString(subName) || subName === ""){
error("Subcookie name must be a non-empty string.");
}
}
/**
* Cookie utility.
* @class Cookie
* @static
*/
Y.Cookie = {
//-------------------------------------------------------------------------
// Private Methods
//-------------------------------------------------------------------------
/**
* Creates a cookie string that can be assigned into document.cookie.
* @param {String} name The name of the cookie.
* @param {String} value The value of the cookie.
* @param {Boolean} encodeValue True to encode the value, false to leave as-is.
* @param {Object} options (Optional) Options for the cookie.
* @return {String} The formatted cookie string.
* @method _createCookieString
* @private
* @static
*/
_createCookieString : function (name /*:String*/, value /*:Variant*/, encodeValue /*:Boolean*/, options /*:Object*/) /*:String*/ {
options = options || {};
var text /*:String*/ = encode(name) + "=" + (encodeValue ? encode(value) : value),
expires = options.expires,
path = options.path,
domain = options.domain;
if (isObject(options)){
//expiration date
if (expires instanceof Date){
text += "; expires=" + expires.toUTCString();
}
//path
if (isString(path) && path !== ""){
text += "; path=" + path;
}
//domain
if (isString(domain) && domain !== ""){
text += "; domain=" + domain;
}
//secure
if (options.secure === true){
text += "; secure";
}
}
return text;
},
/**
* Formats a cookie value for an object containing multiple values.
* @param {Object} hash An object of key-value pairs to create a string for.
* @return {String} A string suitable for use as a cookie value.
* @method _createCookieHashString
* @private
* @static
*/
_createCookieHashString : function (hash /*:Object*/) /*:String*/ {
if (!isObject(hash)){
error("Cookie._createCookieHashString(): Argument must be an object.");
}
var text /*:Array*/ = [];
O.each(hash, function(value, key){
if (!isFunction(value) && !isUndefined(value)){
text.push(encode(key) + "=" + encode(String(value)));
}
});
return text.join("&");
},
/**
* Parses a cookie hash string into an object.
* @param {String} text The cookie hash string to parse (format: n1=v1&n2=v2).
* @return {Object} An object containing entries for each cookie value.
* @method _parseCookieHash
* @private
* @static
*/
_parseCookieHash : function (text) {
var hashParts = text.split("&"),
hashPart = NULL,
hash = {};
if (text.length){
for (var i=0, len=hashParts.length; i < len; i++){
hashPart = hashParts[i].split("=");
hash[decode(hashPart[0])] = decode(hashPart[1]);
}
}
return hash;
},
/**
* Parses a cookie string into an object representing all accessible cookies.
* @param {String} text The cookie string to parse.
* @param {Boolean} shouldDecode (Optional) Indicates if the cookie values should be decoded or not. Default is true.
* @return {Object} An object containing entries for each accessible cookie.
* @method _parseCookieString
* @private
* @static
*/
_parseCookieString : function (text /*:String*/, shouldDecode /*:Boolean*/) /*:Object*/ {
var cookies /*:Object*/ = {};
if (isString(text) && text.length > 0) {
var decodeValue = (shouldDecode === false ? function(s){return s;} : decode),
cookieParts = text.split(/;\s/g),
cookieName = NULL,
cookieValue = NULL,
cookieNameValue = NULL;
for (var i=0, len=cookieParts.length; i < len; i++){
//check for normally-formatted cookie (name-value)
cookieNameValue = cookieParts[i].match(/([^=]+)=/i);
if (cookieNameValue instanceof Array){
try {
cookieName = decode(cookieNameValue[1]);
cookieValue = decodeValue(cookieParts[i].substring(cookieNameValue[1].length+1));
} catch (ex){
//intentionally ignore the cookie - the encoding is wrong
}
} else {
//means the cookie does not have an "=", so treat it as a boolean flag
cookieName = decode(cookieParts[i]);
cookieValue = "";
}
cookies[cookieName] = cookieValue;
}
}
return cookies;
},
//-------------------------------------------------------------------------
// Public Methods
//-------------------------------------------------------------------------
/**
* Determines if the cookie with the given name exists. This is useful for
* Boolean cookies (those that do not follow the name=value convention).
* @param {String} name The name of the cookie to check.
* @return {Boolean} True if the cookie exists, false if not.
* @method exists
* @static
*/
exists: function(name) {
validateCookieName(name); //throws error
var cookies = this._parseCookieString(doc.cookie, true);
return cookies.hasOwnProperty(name);
},
/**
* Returns the cookie value for the given name.
* @param {String} name The name of the cookie to retrieve.
* @param {Function|Object} options (Optional) An object containing one or more
* cookie options: raw (true/false) and converter (a function).
* The converter function is run on the value before returning it. The
* function is not used if the cookie doesn't exist. The function can be
* passed instead of the options object for backwards compatibility. When
* raw is set to true, the cookie value is not URI decoded.
* @return {Variant} If no converter is specified, returns a string or null if
* the cookie doesn't exist. If the converter is specified, returns the value
* returned from the converter or null if the cookie doesn't exist.
* @method get
* @static
*/
get : function (name, options) {
validateCookieName(name); //throws error
var cookies,
cookie,
converter;
//if options is a function, then it's the converter
if (isFunction(options)) {
converter = options;
options = {};
} else if (isObject(options)) {
converter = options.converter;
} else {
options = {};
}
cookies = this._parseCookieString(doc.cookie, !options.raw);
cookie = cookies[name];
//should return null, not undefined if the cookie doesn't exist
if (isUndefined(cookie)) {
return NULL;
}
if (!isFunction(converter)){
return cookie;
} else {
return converter(cookie);
}
},
/**
* Returns the value of a subcookie.
* @param {String} name The name of the cookie to retrieve.
* @param {String} subName The name of the subcookie to retrieve.
* @param {Function} converter (Optional) A function to run on the value before returning
* it. The function is not used if the cookie doesn't exist.
* @return {Variant} If the cookie doesn't exist, null is returned. If the subcookie
* doesn't exist, null if also returned. If no converter is specified and the
* subcookie exists, a string is returned. If a converter is specified and the
* subcookie exists, the value returned from the converter is returned.
* @method getSub
* @static
*/
getSub : function (name /*:String*/, subName /*:String*/, converter /*:Function*/) /*:Variant*/ {
var hash /*:Variant*/ = this.getSubs(name);
if (hash !== NULL) {
validateSubcookieName(subName); //throws error
if (isUndefined(hash[subName])){
return NULL;
}
if (!isFunction(converter)){
return hash[subName];
} else {
return converter(hash[subName]);
}
} else {
return NULL;
}
},
/**
* Returns an object containing name-value pairs stored in the cookie with the given name.
* @param {String} name The name of the cookie to retrieve.
* @return {Object} An object of name-value pairs if the cookie with the given name
* exists, null if it does not.
* @method getSubs
* @static
*/
getSubs : function (name) {
validateCookieName(name); //throws error
var cookies = this._parseCookieString(doc.cookie, false);
if (isString(cookies[name])){
return this._parseCookieHash(cookies[name]);
}
return NULL;
},
/**
* Removes a cookie from the machine by setting its expiration date to
* sometime in the past.
* @param {String} name The name of the cookie to remove.
* @param {Object} options (Optional) An object containing one or more
* cookie options: path (a string), domain (a string),
* and secure (true/false). The expires option will be overwritten
* by the method.
* @return {String} The created cookie string.
* @method remove
* @static
*/
remove : function (name, options) {
validateCookieName(name); //throws error
//set options
options = Y.merge(options || {}, {
expires: new Date(0)
});
//set cookie
return this.set(name, "", options);
},
/**
* Removes a sub cookie with a given name.
* @param {String} name The name of the cookie in which the subcookie exists.
* @param {String} subName The name of the subcookie to remove.
* @param {Object} options (Optional) An object containing one or more
* cookie options: path (a string), domain (a string), expires (a Date object),
* removeIfEmpty (true/false), and secure (true/false). This must be the same
* settings as the original subcookie.
* @return {String} The created cookie string.
* @method removeSub
* @static
*/
removeSub : function(name, subName, options) {
validateCookieName(name); //throws error
validateSubcookieName(subName); //throws error
options = options || {};
//get all subcookies for this cookie
var subs = this.getSubs(name);
//delete the indicated subcookie
if (isObject(subs) && subs.hasOwnProperty(subName)){
delete subs[subName];
if (!options.removeIfEmpty) {
//reset the cookie
return this.setSubs(name, subs, options);
} else {
//reset the cookie if there are subcookies left, else remove
for (var key in subs){
if (subs.hasOwnProperty(key) && !isFunction(subs[key]) && !isUndefined(subs[key])){
return this.setSubs(name, subs, options);
}
}
return this.remove(name, options);
}
} else {
return "";
}
},
/**
* Sets a cookie with a given name and value.
* @param {String} name The name of the cookie to set.
* @param {Variant} value The value to set for the cookie.
* @param {Object} options (Optional) An object containing one or more
* cookie options: path (a string), domain (a string), expires (a Date object),
* secure (true/false), and raw (true/false). Setting raw to true indicates
* that the cookie should not be URI encoded before being set.
* @return {String} The created cookie string.
* @method set
* @static
*/
set : function (name, value, options) {
validateCookieName(name); //throws error
if (isUndefined(value)){
error("Cookie.set(): Value cannot be undefined.");
}
options = options || {};
var text = this._createCookieString(name, value, !options.raw, options);
doc.cookie = text;
return text;
},
/**
* Sets a sub cookie with a given name to a particular value.
* @param {String} name The name of the cookie to set.
* @param {String} subName The name of the subcookie to set.
* @param {Variant} value The value to set.
* @param {Object} options (Optional) An object containing one or more
* cookie options: path (a string), domain (a string), expires (a Date object),
* and secure (true/false).
* @return {String} The created cookie string.
* @method setSub
* @static
*/
setSub : function (name, subName, value, options) {
validateCookieName(name); //throws error
validateSubcookieName(subName); //throws error
if (isUndefined(value)){
error("Cookie.setSub(): Subcookie value cannot be undefined.");
}
var hash = this.getSubs(name);
if (!isObject(hash)){
hash = {};
}
hash[subName] = value;
return this.setSubs(name, hash, options);
},
/**
* Sets a cookie with a given name to contain a hash of name-value pairs.
* @param {String} name The name of the cookie to set.
* @param {Object} value An object containing name-value pairs.
* @param {Object} options (Optional) An object containing one or more
* cookie options: path (a string), domain (a string), expires (a Date object),
* and secure (true/false).
* @return {String} The created cookie string.
* @method setSubs
* @static
*/
setSubs : function (name, value, options) {
validateCookieName(name); //throws error
if (!isObject(value)){
error("Cookie.setSubs(): Cookie value must be an object.");
}
var text /*:String*/ = this._createCookieString(name, this._createCookieHashString(value), false, options);
doc.cookie = text;
return text;
}
};
}, '3.0.0' ,{requires:['yui-base']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("dataschema-array",function(C){var A=C.Lang,B={apply:function(F,G){var D=G,E={results:[],meta:{}};if(A.isArray(D)){if(A.isArray(F.resultFields)){E=B._parseResults(F.resultFields,D,E);}else{E.results=D;}}else{E.error=new Error("Array schema parse failure");}return E;},_parseResults:function(H,K,D){var G=[],O,N,I,J,M,L,F,E;for(F=K.length-1;F>-1;F--){O={};N=K[F];I=(A.isObject(N)&&!A.isFunction(N))?2:(A.isArray(N))?1:(A.isString(N))?0:-1;if(I>0){for(E=H.length-1;E>-1;E--){J=H[E];M=(!A.isUndefined(J.key))?J.key:J;L=(!A.isUndefined(N[M]))?N[M]:N[E];O[M]=C.DataSchema.Base.parse(L,J);}}else{if(I===0){O=N;}else{O=null;}}G[F]=O;}D.results=G;return D;}};C.DataSchema.Array=C.mix(B,C.DataSchema.Base);},"3.0.0",{requires:["dataschema-base"]});

View File

@@ -0,0 +1,107 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('dataschema-array', function(Y) {
/**
* Provides a DataSchema implementation which can be used to work with data stored in arrays.
*
* @module dataschema
* @submodule dataschema-array
*/
/**
* Array subclass for the DataSchema Utility.
* @class DataSchema.Array
* @extends DataSchema.Base
* @static
*/
var LANG = Y.Lang,
SchemaArray = {
/////////////////////////////////////////////////////////////////////////////
//
// DataSchema.Array static methods
//
/////////////////////////////////////////////////////////////////////////////
/**
* Applies a given schema to given Array data.
*
* @method apply
* @param schema {Object} Schema to apply.
* @param data {Object} Array data.
* @return {Object} Schema-parsed data.
* @static
*/
apply: function(schema, data) {
var data_in = data,
data_out = {results:[],meta:{}};
if(LANG.isArray(data_in)) {
if(LANG.isArray(schema.resultFields)) {
// Parse results data
data_out = SchemaArray._parseResults(schema.resultFields, data_in, data_out);
}
else {
data_out.results = data_in;
}
}
else {
data_out.error = new Error("Array schema parse failure");
}
return data_out;
},
/**
* Schema-parsed list of results from full data
*
* @method _parseResults
* @param fields {Array} Schema to parse against.
* @param array_in {Array} Array to parse.
* @param data_out {Object} In-progress parsed data to update.
* @return {Object} Parsed data object.
* @static
* @protected
*/
_parseResults: function(fields, array_in, data_out) {
var results = [],
result, item, type, field, key, value, i, j;
for(i=array_in.length-1; i>-1; i--) {
result = {};
item = array_in[i];
type = (LANG.isObject(item) && !LANG.isFunction(item)) ? 2 : (LANG.isArray(item)) ? 1 : (LANG.isString(item)) ? 0 : -1;
if(type > 0) {
for(j=fields.length-1; j>-1; j--) {
field = fields[j];
key = (!LANG.isUndefined(field.key)) ? field.key : field;
value = (!LANG.isUndefined(item[key])) ? item[key] : item[j];
result[key] = Y.DataSchema.Base.parse(value, field);
}
}
else if(type === 0) {
result = item;
}
else {
//TODO: null or {}?
result = null;
}
results[i] = result;
}
data_out.results = results;
return data_out;
}
};
Y.DataSchema.Array = Y.mix(SchemaArray, Y.DataSchema.Base);
}, '3.0.0' ,{requires:['dataschema-base']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("dataschema-base",function(B){var A=B.Lang,C={apply:function(D,E){return E;},parse:function(D,E){if(E.parser){var F=(A.isFunction(E.parser))?E.parser:B.Parsers[E.parser+""];if(F){D=F.call(this,D);}else{}}return D;}};B.namespace("DataSchema").Base=C;B.namespace("Parsers");},"3.0.0",{requires:["base"]});

View File

@@ -0,0 +1,73 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('dataschema-base', function(Y) {
/**
* The DataSchema utility provides a common configurable interface for widgets to
* apply a given schema to a variety of data.
*
* @module dataschema
*/
/**
* Provides the base DataSchema implementation, which can be extended to
* create DataSchemas for specific data formats, such XML, JSON, text and
* arrays.
*
* @module dataschema
* @submodule dataschema-base
*/
var LANG = Y.Lang,
/**
* Base class for the YUI DataSchema Utility.
* @class DataSchema.Base
* @static
*/
SchemaBase = {
/**
* Overridable method returns data as-is.
*
* @method apply
* @param schema {Object} Schema to apply.
* @param data {Object} Data.
* @return {Object} Schema-parsed data.
* @static
*/
apply: function(schema, data) {
return data;
},
/**
* Applies field parser, if defined
*
* @method parse
* @param value {Object} Original value.
* @param field {Object} Field.
* @return {Object} Type-converted value.
*/
parse: function(value, field) {
if(field.parser) {
var parser = (LANG.isFunction(field.parser)) ?
field.parser : Y.Parsers[field.parser+''];
if(parser) {
value = parser.call(this, value);
}
else {
}
}
return value;
}
};
Y.namespace("DataSchema").Base = SchemaBase;
Y.namespace("Parsers");
}, '3.0.0' ,{requires:['base']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("dataschema-json",function(C){var A=C.Lang,B={getPath:function(D){var G=null,F=[],E=0;if(D){D=D.replace(/\[(['"])(.*?)\1\]/g,function(I,H,J){F[E]=J;return".@"+(E++);}).replace(/\[(\d+)\]/g,function(I,H){F[E]=parseInt(H,10)|0;return".@"+(E++);}).replace(/^\./,"");if(!/[^\w\.\$@]/.test(D)){G=D.split(".");for(E=G.length-1;E>=0;--E){if(G[E].charAt(0)==="@"){G[E]=F[parseInt(G[E].substr(1),10)];}}}else{}}return G;},getLocationValue:function(G,F){var E=0,D=G.length;for(;E<D;E++){if(!A.isUndefined(F[G[E]])){F=F[G[E]];}else{F=undefined;break;}}return F;},apply:function(F,G){var D=G,E={results:[],meta:{}};if(!A.isObject(G)){try{D=C.JSON.parse(G);}catch(H){E.error=H;return E;}}if(A.isObject(D)&&F){if(!A.isUndefined(F.resultListLocator)){E=B._parseResults(F,D,E);}if(!A.isUndefined(F.metaFields)){E=B._parseMeta(F.metaFields,D,E);}}else{E.error=new Error("JSON schema parse failure");}return E;},_parseResults:function(H,D,G){var F=[],I,E;if(H.resultListLocator){I=B.getPath(H.resultListLocator);if(I){F=B.getLocationValue(I,D);if(F===undefined){G.results=[];E=new Error("JSON results retrieval failure");}else{if(A.isArray(H.resultFields)&&A.isArray(F)){G=B._getFieldValues(H.resultFields,F,G);}else{G.results=[];E=new Error("JSON Schema fields retrieval failure");}}}else{E=new Error("JSON Schema results locator failure");}if(E){G.error=E;}}return G;},_getFieldValues:function(K,P,E){var G=[],M=K.length,H,F,O,Q,S,D,J=[],N=[],L=[],R,I;for(H=0;H<M;H++){O=K[H];Q=O.key||O;S=B.getPath(Q);if(S){if(S.length===1){J[J.length]={key:Q,path:S[0]};}else{N[N.length]={key:Q,path:S};}}else{}D=(A.isFunction(O.parser))?O.parser:C.Parsers[O.parser+""];if(D){L[L.length]={key:Q,parser:D};}}for(H=P.length-1;H>=0;--H){I={};R=P[H];if(R){for(F=J.length-1;F>=0;--F){I[J[F].key]=C.DataSchema.Base.parse((A.isUndefined(R[J[F].path])?R[F]:R[J[F].path]),J[F]);}for(F=N.length-1;F>=0;--F){I[N[F].key]=C.DataSchema.Base.parse((B.getLocationValue(N[F].path,R)),N[F]);}for(F=L.length-1;F>=0;--F){Q=L[F].key;I[Q]=L[F].parser(I[Q]);if(A.isUndefined(I[Q])){I[Q]=null;}}G[H]=I;}}E.results=G;return E;},_parseMeta:function(G,D,F){if(A.isObject(G)){var E,H;for(E in G){if(G.hasOwnProperty(E)){H=B.getPath(G[E]);if(H&&D){F.meta[E]=B.getLocationValue(H,D);}}}}else{F.error=new Error("JSON meta data retrieval failure");}return F;}};C.DataSchema.JSON=C.mix(B,C.DataSchema.Base);},"3.0.0",{requires:["json","dataschema-base"]});

View File

@@ -0,0 +1,294 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('dataschema-json', function(Y) {
/**
* Provides a DataSchema implementation which can be used to work with JSON data.
*
* @module dataschema
* @submodule dataschema-json
*/
/**
* JSON subclass for the DataSchema Utility.
* @class DataSchema.JSON
* @extends DataSchema.Base
* @static
*/
var LANG = Y.Lang,
SchemaJSON = {
/////////////////////////////////////////////////////////////////////////////
//
// DataSchema.JSON static methods
//
/////////////////////////////////////////////////////////////////////////////
/**
* Utility function converts JSON locator strings into walkable paths
*
* @method DataSchema.JSON.getPath
* @param locator {String} JSON value locator.
* @return {String[]} Walkable path to data value.
* @static
*/
getPath: function(locator) {
var path = null,
keys = [],
i = 0;
if (locator) {
// Strip the ["string keys"] and [1] array indexes
locator = locator.
replace(/\[(['"])(.*?)\1\]/g,
function (x,$1,$2) {keys[i]=$2;return '.@'+(i++);}).
replace(/\[(\d+)\]/g,
function (x,$1) {keys[i]=parseInt($1,10)|0;return '.@'+(i++);}).
replace(/^\./,''); // remove leading dot
// Validate against problematic characters.
if (!/[^\w\.\$@]/.test(locator)) {
path = locator.split('.');
for (i=path.length-1; i >= 0; --i) {
if (path[i].charAt(0) === '@') {
path[i] = keys[parseInt(path[i].substr(1),10)];
}
}
}
else {
}
}
return path;
},
/**
* Utility function to walk a path and return the value located there.
*
* @method DataSchema.JSON.getLocationValue
* @param path {String[]} Locator path.
* @param data {String} Data to traverse.
* @return {Object} Data value at location.
* @static
*/
getLocationValue: function (path, data) {
var i = 0,
len = path.length;
for (;i<len;i++) {
if(!LANG.isUndefined(data[path[i]])) {
data = data[path[i]];
}
else {
data = undefined;
break;
}
}
return data;
},
/**
* Applies a given schema to given JSON data.
*
* @method apply
* @param schema {Object} Schema to apply.
* @param data {Object} JSON data.
* @return {Object} Schema-parsed data.
* @static
*/
apply: function(schema, data) {
var data_in = data,
data_out = {results:[],meta:{}};
// Convert incoming JSON strings
if(!LANG.isObject(data)) {
try {
data_in = Y.JSON.parse(data);
}
catch(e) {
data_out.error = e;
return data_out;
}
}
if(LANG.isObject(data_in) && schema) {
// Parse results data
if(!LANG.isUndefined(schema.resultListLocator)) {
data_out = SchemaJSON._parseResults(schema, data_in, data_out);
}
// Parse meta data
if(!LANG.isUndefined(schema.metaFields)) {
data_out = SchemaJSON._parseMeta(schema.metaFields, data_in, data_out);
}
}
else {
data_out.error = new Error("JSON schema parse failure");
}
return data_out;
},
/**
* Schema-parsed list of results from full data
*
* @method _parseResults
* @param schema {Object} Schema to parse against.
* @param json_in {Object} JSON to parse.
* @param data_out {Object} In-progress parsed data to update.
* @return {Object} Parsed data object.
* @static
* @protected
*/
_parseResults: function(schema, json_in, data_out) {
var results = [],
path,
error;
if(schema.resultListLocator) {
path = SchemaJSON.getPath(schema.resultListLocator);
if(path) {
results = SchemaJSON.getLocationValue(path, json_in);
if (results === undefined) {
data_out.results = [];
error = new Error("JSON results retrieval failure");
}
else {
if(LANG.isArray(schema.resultFields) && LANG.isArray(results)) {
data_out = SchemaJSON._getFieldValues(schema.resultFields, results, data_out);
}
else {
data_out.results = [];
error = new Error("JSON Schema fields retrieval failure");
}
}
}
else {
error = new Error("JSON Schema results locator failure");
}
if (error) {
data_out.error = error;
}
}
return data_out;
},
/**
* Get field data values out of list of full results
*
* @method _getFieldValues
* @param fields {Array} Fields to find.
* @param array_in {Array} Results to parse.
* @param data_out {Object} In-progress parsed data to update.
* @return {Object} Parsed data object.
* @static
* @protected
*/
_getFieldValues: function(fields, array_in, data_out) {
var results = [],
len = fields.length,
i, j,
field, key, path, parser,
simplePaths = [], complexPaths = [], fieldParsers = [],
result, record;
// First collect hashes of simple paths, complex paths, and parsers
for (i=0; i<len; i++) {
field = fields[i]; // A field can be a simple string or a hash
key = field.key || field; // Find the key
// Validate and store locators for later
path = SchemaJSON.getPath(key);
if (path) {
if (path.length === 1) {
simplePaths[simplePaths.length] = {key:key, path:path[0]};
} else {
complexPaths[complexPaths.length] = {key:key, path:path};
}
} else {
}
// Validate and store parsers for later
//TODO: use Y.DataSchema.parse?
parser = (LANG.isFunction(field.parser)) ? field.parser : Y.Parsers[field.parser+''];
if (parser) {
fieldParsers[fieldParsers.length] = {key:key, parser:parser};
}
}
// Traverse list of array_in, creating records of simple fields,
// complex fields, and applying parsers as necessary
for (i=array_in.length-1; i>=0; --i) {
record = {};
result = array_in[i];
if(result) {
// Cycle through simpleLocators
for (j=simplePaths.length-1; j>=0; --j) {
// Bug 1777850: The result might be an array instead of object
record[simplePaths[j].key] = Y.DataSchema.Base.parse(
(LANG.isUndefined(result[simplePaths[j].path]) ?
result[j] : result[simplePaths[j].path]), simplePaths[j]);
}
// Cycle through complexLocators
for (j=complexPaths.length - 1; j>=0; --j) {
record[complexPaths[j].key] = Y.DataSchema.Base.parse(
(SchemaJSON.getLocationValue(complexPaths[j].path, result)), complexPaths[j] );
}
// Cycle through fieldParsers
for (j=fieldParsers.length-1; j>=0; --j) {
key = fieldParsers[j].key;
record[key] = fieldParsers[j].parser(record[key]);
// Safety net
if (LANG.isUndefined(record[key])) {
record[key] = null;
}
}
results[i] = record;
}
}
data_out.results = results;
return data_out;
},
/**
* Parses results data according to schema
*
* @method _parseMeta
* @param metaFields {Object} Metafields definitions.
* @param json_in {Object} JSON to parse.
* @param data_out {Object} In-progress parsed data to update.
* @return {Object} Schema-parsed meta data.
* @static
* @protected
*/
_parseMeta: function(metaFields, json_in, data_out) {
if(LANG.isObject(metaFields)) {
var key, path;
for(key in metaFields) {
if (metaFields.hasOwnProperty(key)) {
path = SchemaJSON.getPath(metaFields[key]);
if (path && json_in) {
data_out.meta[key] = SchemaJSON.getLocationValue(path, json_in);
}
}
}
}
else {
data_out.error = new Error("JSON meta data retrieval failure");
}
return data_out;
}
};
Y.DataSchema.JSON = Y.mix(SchemaJSON, Y.DataSchema.Base);
}, '3.0.0' ,{requires:['json', 'dataschema-base']});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("dataschema-text",function(C){var B=C.Lang,A={apply:function(F,G){var D=G,E={results:[],meta:{}};if(B.isString(D)&&B.isString(F.resultDelimiter)){E=A._parseResults(F,D,E);}else{E.error=new Error("Text schema parse failure");}return E;},_parseResults:function(D,K,E){var I=D.resultDelimiter,H=[],L,P,S,R,J,N,Q,O,G,F,M=K.length-I.length;if(K.substr(M)==I){K=K.substr(0,M);}L=K.split(D.resultDelimiter);for(G=L.length-1;G>-1;G--){S={};R=L[G];if(B.isString(D.fieldDelimiter)){P=R.split(D.fieldDelimiter);if(B.isArray(D.resultFields)){J=D.resultFields;for(F=J.length-1;F>-1;F--){N=J[F];Q=(!B.isUndefined(N.key))?N.key:N;O=(!B.isUndefined(P[Q]))?P[Q]:P[F];S[Q]=C.DataSchema.Base.parse(O,N);}}}else{S=R;}H[G]=S;}E.results=H;return E;}};C.DataSchema.Text=C.mix(A,C.DataSchema.Base);},"3.0.0",{requires:["dataschema-base"]});

View File

@@ -0,0 +1,116 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('dataschema-text', function(Y) {
/**
* Provides a DataSchema implementation which can be used to work with delimited text data.
*
* @module dataschema
* @submodule dataschema-text
*/
/**
* Text subclass for the DataSchema Utility.
* @class DataSchema.Text
* @extends DataSchema.Base
* @static
*/
var LANG = Y.Lang,
SchemaText = {
/////////////////////////////////////////////////////////////////////////////
//
// DataSchema.Text static methods
//
/////////////////////////////////////////////////////////////////////////////
/**
* Applies a given schema to given delimited text data.
*
* @method apply
* @param schema {Object} Schema to apply.
* @param data {Object} Text data.
* @return {Object} Schema-parsed data.
* @static
*/
apply: function(schema, data) {
var data_in = data,
data_out = {results:[],meta:{}};
if(LANG.isString(data_in) && LANG.isString(schema.resultDelimiter)) {
// Parse results data
data_out = SchemaText._parseResults(schema, data_in, data_out);
}
else {
data_out.error = new Error("Text schema parse failure");
}
return data_out;
},
/**
* Schema-parsed list of results from full data
*
* @method _parseResults
* @param schema {Array} Schema to parse against.
* @param text_in {String} Text to parse.
* @param data_out {Object} In-progress parsed data to update.
* @return {Object} Parsed data object.
* @static
* @protected
*/
_parseResults: function(schema, text_in, data_out) {
var resultDelim = schema.resultDelimiter,
results = [],
results_in, fields_in, result, item, fields, field, key, value, i, j,
// Delete final delimiter at end of string if there
tmpLength = text_in.length-resultDelim.length;
if(text_in.substr(tmpLength) == resultDelim) {
text_in = text_in.substr(0, tmpLength);
}
// Split into results
results_in = text_in.split(schema.resultDelimiter);
for(i=results_in.length-1; i>-1; i--) {
result = {};
item = results_in[i];
if(LANG.isString(schema.fieldDelimiter)) {
fields_in = item.split(schema.fieldDelimiter);
if(LANG.isArray(schema.resultFields)) {
fields = schema.resultFields;
for(j=fields.length-1; j>-1; j--) {
field = fields[j];
key = (!LANG.isUndefined(field.key)) ? field.key : field;
value = (!LANG.isUndefined(fields_in[key])) ? fields_in[key] : fields_in[j];
result[key] = Y.DataSchema.Base.parse(value, field);
}
}
}
else {
result = item;
}
results[i] = result;
}
data_out.results = results;
return data_out;
}
};
Y.DataSchema.Text = Y.mix(SchemaText, Y.DataSchema.Base);
}, '3.0.0' ,{requires:['dataschema-base']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("dataschema-xml",function(C){var B=C.Lang,A={apply:function(F,G){var D=G,E={results:[],meta:{}};if(D&&D.nodeType&&(D.nodeType===9||D.nodeType===1||D.nodeType===11)&&F){E=A._parseResults(F,D,E);E=A._parseMeta(F.metaFields,D,E);}else{E.error=new Error("XML schema parse failure");}return E;},_getLocationValue:function(K,H){var F=K.locator||K.key||K,E=H.ownerDocument||H,D,G,I=null;try{if(!B.isUndefined(E.evaluate)){D=E.evaluate(F,H,E.createNSResolver(!H.ownerDocument?H.documentElement:H.ownerDocument.documentElement),0,null);while(G=D.iterateNext()){I=G.textContent;}}else{E.setProperty("SelectionLanguage","XPath");D=H.selectNodes(F)[0];I=D.value||D.text||null;}return C.DataSchema.Base.parse(I,K);}catch(J){}},_parseMeta:function(H,G,F){if(B.isObject(H)){var E,D=G.ownerDocument||G;for(E in H){if(H.hasOwnProperty(E)){F.meta[E]=A._getLocationValue(H[E],D);}}}return F;},_parseResults:function(F,K,G){if(F.resultListLocator&&B.isArray(F.resultFields)){var E=K.getElementsByTagName(F.resultListLocator),L=F.resultFields,J=[],D,M,N,I,H;if(E.length){for(I=E.length-1;I>=0;I--){N={};D=E[I];for(H=L.length-1;H>=0;H--){M=L[H];N[M.key||M]=A._getLocationValue(M,D);}J[I]=N;}G.results=J;}else{G.error=new Error("XML schema result nodes retrieval failure");}}return G;}};C.DataSchema.XML=C.mix(A,C.DataSchema.Base);},"3.0.0",{requires:["dataschema-base"]});

View File

@@ -0,0 +1,164 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('dataschema-xml', function(Y) {
/**
* Provides a DataSchema implementation which can be used to work with XML data.
*
* @module dataschema
* @submodule dataschema-xml
*/
var LANG = Y.Lang,
/**
* XML subclass for the DataSchema Utility.
* @class DataSchema.XML
* @extends DataSchema.Base
* @static
*/
SchemaXML = {
/////////////////////////////////////////////////////////////////////////////
//
// DataSchema.XML static methods
//
/////////////////////////////////////////////////////////////////////////////
/**
* Applies a given schema to given XML data.
*
* @method apply
* @param schema {Object} Schema to apply.
* @param data {XMLDoc} XML document.
* @return {Object} Schema-parsed data.
* @static
*/
apply: function(schema, data) {
var xmldoc = data,
data_out = {results:[],meta:{}};
if(xmldoc && xmldoc.nodeType && (xmldoc.nodeType === 9 || xmldoc.nodeType === 1 || xmldoc.nodeType === 11) && schema) {
// Parse results data
data_out = SchemaXML._parseResults(schema, xmldoc, data_out);
// Parse meta data
data_out = SchemaXML._parseMeta(schema.metaFields, xmldoc, data_out);
}
else {
data_out.error = new Error("XML schema parse failure");
}
return data_out;
},
/**
* Get an XPath-specified value for a given field from an XML node or document.
*
* @method _getLocationValue
* @param field {String | Object} Field definition.
* @param context {Object} XML node or document to search within.
* @return {Object} Data value or null.
* @static
* @protected
*/
_getLocationValue: function(field, context) {
var locator = field.locator || field.key || field,
xmldoc = context.ownerDocument || context,
result, res, value = null;
try {
// Standards mode
if(!LANG.isUndefined(xmldoc.evaluate)) {
result = xmldoc.evaluate(locator, context, xmldoc.createNSResolver(!context.ownerDocument ? context.documentElement : context.ownerDocument.documentElement), 0, null);
while(res = result.iterateNext()) {
value = res.textContent;
}
}
// IE mode
else {
xmldoc.setProperty("SelectionLanguage", "XPath");
result = context.selectNodes(locator)[0];
value = result.value || result.text || null;
}
return Y.DataSchema.Base.parse(value, field);
}
catch(e) {
}
},
/**
* Parses results data according to schema
*
* @method _parseMeta
* @param xmldoc_in {Object} XML document parse.
* @param data_out {Object} In-progress schema-parsed data to update.
* @return {Object} Schema-parsed data.
* @static
* @protected
*/
_parseMeta: function(metaFields, xmldoc_in, data_out) {
if(LANG.isObject(metaFields)) {
var key,
xmldoc = xmldoc_in.ownerDocument || xmldoc_in;
for(key in metaFields) {
if (metaFields.hasOwnProperty(key)) {
data_out.meta[key] = SchemaXML._getLocationValue(metaFields[key], xmldoc);
}
}
}
return data_out;
},
/**
* Schema-parsed list of results from full data
*
* @method _parseResults
* @param schema {Object} Schema to parse against.
* @param xmldoc_in {Object} XML document parse.
* @param data_out {Object} In-progress schema-parsed data to update.
* @return {Object} Schema-parsed data.
* @static
* @protected
*/
_parseResults: function(schema, xmldoc_in, data_out) {
if(schema.resultListLocator && LANG.isArray(schema.resultFields)) {
var nodeList = xmldoc_in.getElementsByTagName(schema.resultListLocator),
fields = schema.resultFields,
results = [],
node, field, result, i, j;
if(nodeList.length) {
// Loop through each result node
for(i=nodeList.length-1; i>= 0; i--) {
result = {};
node = nodeList[i];
// Find each field value
for(j=fields.length-1; j>= 0; j--) {
field = fields[j];
result[field.key || field] = SchemaXML._getLocationValue(field, node);
}
results[i] = result;
}
data_out.results = results;
}
else {
data_out.error = new Error("XML schema result nodes retrieval failure");
}
}
return data_out;
}
};
Y.DataSchema.XML = Y.mix(SchemaXML, Y.DataSchema.Base);
}, '3.0.0' ,{requires:['dataschema-base']});

View File

@@ -0,0 +1,735 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('dataschema-base', function(Y) {
/**
* The DataSchema utility provides a common configurable interface for widgets to
* apply a given schema to a variety of data.
*
* @module dataschema
*/
/**
* Provides the base DataSchema implementation, which can be extended to
* create DataSchemas for specific data formats, such XML, JSON, text and
* arrays.
*
* @module dataschema
* @submodule dataschema-base
*/
var LANG = Y.Lang,
/**
* Base class for the YUI DataSchema Utility.
* @class DataSchema.Base
* @static
*/
SchemaBase = {
/**
* Overridable method returns data as-is.
*
* @method apply
* @param schema {Object} Schema to apply.
* @param data {Object} Data.
* @return {Object} Schema-parsed data.
* @static
*/
apply: function(schema, data) {
return data;
},
/**
* Applies field parser, if defined
*
* @method parse
* @param value {Object} Original value.
* @param field {Object} Field.
* @return {Object} Type-converted value.
*/
parse: function(value, field) {
if(field.parser) {
var parser = (LANG.isFunction(field.parser)) ?
field.parser : Y.Parsers[field.parser+''];
if(parser) {
value = parser.call(this, value);
}
else {
}
}
return value;
}
};
Y.namespace("DataSchema").Base = SchemaBase;
Y.namespace("Parsers");
}, '3.0.0' ,{requires:['base']});
YUI.add('dataschema-json', function(Y) {
/**
* Provides a DataSchema implementation which can be used to work with JSON data.
*
* @module dataschema
* @submodule dataschema-json
*/
/**
* JSON subclass for the DataSchema Utility.
* @class DataSchema.JSON
* @extends DataSchema.Base
* @static
*/
var LANG = Y.Lang,
SchemaJSON = {
/////////////////////////////////////////////////////////////////////////////
//
// DataSchema.JSON static methods
//
/////////////////////////////////////////////////////////////////////////////
/**
* Utility function converts JSON locator strings into walkable paths
*
* @method DataSchema.JSON.getPath
* @param locator {String} JSON value locator.
* @return {String[]} Walkable path to data value.
* @static
*/
getPath: function(locator) {
var path = null,
keys = [],
i = 0;
if (locator) {
// Strip the ["string keys"] and [1] array indexes
locator = locator.
replace(/\[(['"])(.*?)\1\]/g,
function (x,$1,$2) {keys[i]=$2;return '.@'+(i++);}).
replace(/\[(\d+)\]/g,
function (x,$1) {keys[i]=parseInt($1,10)|0;return '.@'+(i++);}).
replace(/^\./,''); // remove leading dot
// Validate against problematic characters.
if (!/[^\w\.\$@]/.test(locator)) {
path = locator.split('.');
for (i=path.length-1; i >= 0; --i) {
if (path[i].charAt(0) === '@') {
path[i] = keys[parseInt(path[i].substr(1),10)];
}
}
}
else {
}
}
return path;
},
/**
* Utility function to walk a path and return the value located there.
*
* @method DataSchema.JSON.getLocationValue
* @param path {String[]} Locator path.
* @param data {String} Data to traverse.
* @return {Object} Data value at location.
* @static
*/
getLocationValue: function (path, data) {
var i = 0,
len = path.length;
for (;i<len;i++) {
if(!LANG.isUndefined(data[path[i]])) {
data = data[path[i]];
}
else {
data = undefined;
break;
}
}
return data;
},
/**
* Applies a given schema to given JSON data.
*
* @method apply
* @param schema {Object} Schema to apply.
* @param data {Object} JSON data.
* @return {Object} Schema-parsed data.
* @static
*/
apply: function(schema, data) {
var data_in = data,
data_out = {results:[],meta:{}};
// Convert incoming JSON strings
if(!LANG.isObject(data)) {
try {
data_in = Y.JSON.parse(data);
}
catch(e) {
data_out.error = e;
return data_out;
}
}
if(LANG.isObject(data_in) && schema) {
// Parse results data
if(!LANG.isUndefined(schema.resultListLocator)) {
data_out = SchemaJSON._parseResults(schema, data_in, data_out);
}
// Parse meta data
if(!LANG.isUndefined(schema.metaFields)) {
data_out = SchemaJSON._parseMeta(schema.metaFields, data_in, data_out);
}
}
else {
data_out.error = new Error("JSON schema parse failure");
}
return data_out;
},
/**
* Schema-parsed list of results from full data
*
* @method _parseResults
* @param schema {Object} Schema to parse against.
* @param json_in {Object} JSON to parse.
* @param data_out {Object} In-progress parsed data to update.
* @return {Object} Parsed data object.
* @static
* @protected
*/
_parseResults: function(schema, json_in, data_out) {
var results = [],
path,
error;
if(schema.resultListLocator) {
path = SchemaJSON.getPath(schema.resultListLocator);
if(path) {
results = SchemaJSON.getLocationValue(path, json_in);
if (results === undefined) {
data_out.results = [];
error = new Error("JSON results retrieval failure");
}
else {
if(LANG.isArray(schema.resultFields) && LANG.isArray(results)) {
data_out = SchemaJSON._getFieldValues(schema.resultFields, results, data_out);
}
else {
data_out.results = [];
error = new Error("JSON Schema fields retrieval failure");
}
}
}
else {
error = new Error("JSON Schema results locator failure");
}
if (error) {
data_out.error = error;
}
}
return data_out;
},
/**
* Get field data values out of list of full results
*
* @method _getFieldValues
* @param fields {Array} Fields to find.
* @param array_in {Array} Results to parse.
* @param data_out {Object} In-progress parsed data to update.
* @return {Object} Parsed data object.
* @static
* @protected
*/
_getFieldValues: function(fields, array_in, data_out) {
var results = [],
len = fields.length,
i, j,
field, key, path, parser,
simplePaths = [], complexPaths = [], fieldParsers = [],
result, record;
// First collect hashes of simple paths, complex paths, and parsers
for (i=0; i<len; i++) {
field = fields[i]; // A field can be a simple string or a hash
key = field.key || field; // Find the key
// Validate and store locators for later
path = SchemaJSON.getPath(key);
if (path) {
if (path.length === 1) {
simplePaths[simplePaths.length] = {key:key, path:path[0]};
} else {
complexPaths[complexPaths.length] = {key:key, path:path};
}
} else {
}
// Validate and store parsers for later
//TODO: use Y.DataSchema.parse?
parser = (LANG.isFunction(field.parser)) ? field.parser : Y.Parsers[field.parser+''];
if (parser) {
fieldParsers[fieldParsers.length] = {key:key, parser:parser};
}
}
// Traverse list of array_in, creating records of simple fields,
// complex fields, and applying parsers as necessary
for (i=array_in.length-1; i>=0; --i) {
record = {};
result = array_in[i];
if(result) {
// Cycle through simpleLocators
for (j=simplePaths.length-1; j>=0; --j) {
// Bug 1777850: The result might be an array instead of object
record[simplePaths[j].key] = Y.DataSchema.Base.parse(
(LANG.isUndefined(result[simplePaths[j].path]) ?
result[j] : result[simplePaths[j].path]), simplePaths[j]);
}
// Cycle through complexLocators
for (j=complexPaths.length - 1; j>=0; --j) {
record[complexPaths[j].key] = Y.DataSchema.Base.parse(
(SchemaJSON.getLocationValue(complexPaths[j].path, result)), complexPaths[j] );
}
// Cycle through fieldParsers
for (j=fieldParsers.length-1; j>=0; --j) {
key = fieldParsers[j].key;
record[key] = fieldParsers[j].parser(record[key]);
// Safety net
if (LANG.isUndefined(record[key])) {
record[key] = null;
}
}
results[i] = record;
}
}
data_out.results = results;
return data_out;
},
/**
* Parses results data according to schema
*
* @method _parseMeta
* @param metaFields {Object} Metafields definitions.
* @param json_in {Object} JSON to parse.
* @param data_out {Object} In-progress parsed data to update.
* @return {Object} Schema-parsed meta data.
* @static
* @protected
*/
_parseMeta: function(metaFields, json_in, data_out) {
if(LANG.isObject(metaFields)) {
var key, path;
for(key in metaFields) {
if (metaFields.hasOwnProperty(key)) {
path = SchemaJSON.getPath(metaFields[key]);
if (path && json_in) {
data_out.meta[key] = SchemaJSON.getLocationValue(path, json_in);
}
}
}
}
else {
data_out.error = new Error("JSON meta data retrieval failure");
}
return data_out;
}
};
Y.DataSchema.JSON = Y.mix(SchemaJSON, Y.DataSchema.Base);
}, '3.0.0' ,{requires:['json', 'dataschema-base']});
YUI.add('dataschema-xml', function(Y) {
/**
* Provides a DataSchema implementation which can be used to work with XML data.
*
* @module dataschema
* @submodule dataschema-xml
*/
var LANG = Y.Lang,
/**
* XML subclass for the DataSchema Utility.
* @class DataSchema.XML
* @extends DataSchema.Base
* @static
*/
SchemaXML = {
/////////////////////////////////////////////////////////////////////////////
//
// DataSchema.XML static methods
//
/////////////////////////////////////////////////////////////////////////////
/**
* Applies a given schema to given XML data.
*
* @method apply
* @param schema {Object} Schema to apply.
* @param data {XMLDoc} XML document.
* @return {Object} Schema-parsed data.
* @static
*/
apply: function(schema, data) {
var xmldoc = data,
data_out = {results:[],meta:{}};
if(xmldoc && xmldoc.nodeType && (xmldoc.nodeType === 9 || xmldoc.nodeType === 1 || xmldoc.nodeType === 11) && schema) {
// Parse results data
data_out = SchemaXML._parseResults(schema, xmldoc, data_out);
// Parse meta data
data_out = SchemaXML._parseMeta(schema.metaFields, xmldoc, data_out);
}
else {
data_out.error = new Error("XML schema parse failure");
}
return data_out;
},
/**
* Get an XPath-specified value for a given field from an XML node or document.
*
* @method _getLocationValue
* @param field {String | Object} Field definition.
* @param context {Object} XML node or document to search within.
* @return {Object} Data value or null.
* @static
* @protected
*/
_getLocationValue: function(field, context) {
var locator = field.locator || field.key || field,
xmldoc = context.ownerDocument || context,
result, res, value = null;
try {
// Standards mode
if(!LANG.isUndefined(xmldoc.evaluate)) {
result = xmldoc.evaluate(locator, context, xmldoc.createNSResolver(!context.ownerDocument ? context.documentElement : context.ownerDocument.documentElement), 0, null);
while(res = result.iterateNext()) {
value = res.textContent;
}
}
// IE mode
else {
xmldoc.setProperty("SelectionLanguage", "XPath");
result = context.selectNodes(locator)[0];
value = result.value || result.text || null;
}
return Y.DataSchema.Base.parse(value, field);
}
catch(e) {
}
},
/**
* Parses results data according to schema
*
* @method _parseMeta
* @param xmldoc_in {Object} XML document parse.
* @param data_out {Object} In-progress schema-parsed data to update.
* @return {Object} Schema-parsed data.
* @static
* @protected
*/
_parseMeta: function(metaFields, xmldoc_in, data_out) {
if(LANG.isObject(metaFields)) {
var key,
xmldoc = xmldoc_in.ownerDocument || xmldoc_in;
for(key in metaFields) {
if (metaFields.hasOwnProperty(key)) {
data_out.meta[key] = SchemaXML._getLocationValue(metaFields[key], xmldoc);
}
}
}
return data_out;
},
/**
* Schema-parsed list of results from full data
*
* @method _parseResults
* @param schema {Object} Schema to parse against.
* @param xmldoc_in {Object} XML document parse.
* @param data_out {Object} In-progress schema-parsed data to update.
* @return {Object} Schema-parsed data.
* @static
* @protected
*/
_parseResults: function(schema, xmldoc_in, data_out) {
if(schema.resultListLocator && LANG.isArray(schema.resultFields)) {
var nodeList = xmldoc_in.getElementsByTagName(schema.resultListLocator),
fields = schema.resultFields,
results = [],
node, field, result, i, j;
if(nodeList.length) {
// Loop through each result node
for(i=nodeList.length-1; i>= 0; i--) {
result = {};
node = nodeList[i];
// Find each field value
for(j=fields.length-1; j>= 0; j--) {
field = fields[j];
result[field.key || field] = SchemaXML._getLocationValue(field, node);
}
results[i] = result;
}
data_out.results = results;
}
else {
data_out.error = new Error("XML schema result nodes retrieval failure");
}
}
return data_out;
}
};
Y.DataSchema.XML = Y.mix(SchemaXML, Y.DataSchema.Base);
}, '3.0.0' ,{requires:['dataschema-base']});
YUI.add('dataschema-array', function(Y) {
/**
* Provides a DataSchema implementation which can be used to work with data stored in arrays.
*
* @module dataschema
* @submodule dataschema-array
*/
/**
* Array subclass for the DataSchema Utility.
* @class DataSchema.Array
* @extends DataSchema.Base
* @static
*/
var LANG = Y.Lang,
SchemaArray = {
/////////////////////////////////////////////////////////////////////////////
//
// DataSchema.Array static methods
//
/////////////////////////////////////////////////////////////////////////////
/**
* Applies a given schema to given Array data.
*
* @method apply
* @param schema {Object} Schema to apply.
* @param data {Object} Array data.
* @return {Object} Schema-parsed data.
* @static
*/
apply: function(schema, data) {
var data_in = data,
data_out = {results:[],meta:{}};
if(LANG.isArray(data_in)) {
if(LANG.isArray(schema.resultFields)) {
// Parse results data
data_out = SchemaArray._parseResults(schema.resultFields, data_in, data_out);
}
else {
data_out.results = data_in;
}
}
else {
data_out.error = new Error("Array schema parse failure");
}
return data_out;
},
/**
* Schema-parsed list of results from full data
*
* @method _parseResults
* @param fields {Array} Schema to parse against.
* @param array_in {Array} Array to parse.
* @param data_out {Object} In-progress parsed data to update.
* @return {Object} Parsed data object.
* @static
* @protected
*/
_parseResults: function(fields, array_in, data_out) {
var results = [],
result, item, type, field, key, value, i, j;
for(i=array_in.length-1; i>-1; i--) {
result = {};
item = array_in[i];
type = (LANG.isObject(item) && !LANG.isFunction(item)) ? 2 : (LANG.isArray(item)) ? 1 : (LANG.isString(item)) ? 0 : -1;
if(type > 0) {
for(j=fields.length-1; j>-1; j--) {
field = fields[j];
key = (!LANG.isUndefined(field.key)) ? field.key : field;
value = (!LANG.isUndefined(item[key])) ? item[key] : item[j];
result[key] = Y.DataSchema.Base.parse(value, field);
}
}
else if(type === 0) {
result = item;
}
else {
//TODO: null or {}?
result = null;
}
results[i] = result;
}
data_out.results = results;
return data_out;
}
};
Y.DataSchema.Array = Y.mix(SchemaArray, Y.DataSchema.Base);
}, '3.0.0' ,{requires:['dataschema-base']});
YUI.add('dataschema-text', function(Y) {
/**
* Provides a DataSchema implementation which can be used to work with delimited text data.
*
* @module dataschema
* @submodule dataschema-text
*/
/**
* Text subclass for the DataSchema Utility.
* @class DataSchema.Text
* @extends DataSchema.Base
* @static
*/
var LANG = Y.Lang,
SchemaText = {
/////////////////////////////////////////////////////////////////////////////
//
// DataSchema.Text static methods
//
/////////////////////////////////////////////////////////////////////////////
/**
* Applies a given schema to given delimited text data.
*
* @method apply
* @param schema {Object} Schema to apply.
* @param data {Object} Text data.
* @return {Object} Schema-parsed data.
* @static
*/
apply: function(schema, data) {
var data_in = data,
data_out = {results:[],meta:{}};
if(LANG.isString(data_in) && LANG.isString(schema.resultDelimiter)) {
// Parse results data
data_out = SchemaText._parseResults(schema, data_in, data_out);
}
else {
data_out.error = new Error("Text schema parse failure");
}
return data_out;
},
/**
* Schema-parsed list of results from full data
*
* @method _parseResults
* @param schema {Array} Schema to parse against.
* @param text_in {String} Text to parse.
* @param data_out {Object} In-progress parsed data to update.
* @return {Object} Parsed data object.
* @static
* @protected
*/
_parseResults: function(schema, text_in, data_out) {
var resultDelim = schema.resultDelimiter,
results = [],
results_in, fields_in, result, item, fields, field, key, value, i, j,
// Delete final delimiter at end of string if there
tmpLength = text_in.length-resultDelim.length;
if(text_in.substr(tmpLength) == resultDelim) {
text_in = text_in.substr(0, tmpLength);
}
// Split into results
results_in = text_in.split(schema.resultDelimiter);
for(i=results_in.length-1; i>-1; i--) {
result = {};
item = results_in[i];
if(LANG.isString(schema.fieldDelimiter)) {
fields_in = item.split(schema.fieldDelimiter);
if(LANG.isArray(schema.resultFields)) {
fields = schema.resultFields;
for(j=fields.length-1; j>-1; j--) {
field = fields[j];
key = (!LANG.isUndefined(field.key)) ? field.key : field;
value = (!LANG.isUndefined(fields_in[key])) ? fields_in[key] : fields_in[j];
result[key] = Y.DataSchema.Base.parse(value, field);
}
}
}
else {
result = item;
}
results[i] = result;
}
data_out.results = results;
return data_out;
}
};
Y.DataSchema.Text = Y.mix(SchemaText, Y.DataSchema.Base);
}, '3.0.0' ,{requires:['dataschema-base']});
YUI.add('dataschema', function(Y){}, '3.0.0' ,{use:['dataschema-base','dataschema-json','dataschema-xml','dataschema-array','dataschema-text']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("datasource-arrayschema",function(B){var A=function(){A.superclass.constructor.apply(this,arguments);};B.mix(A,{NS:"schema",NAME:"dataSourceArraySchema",ATTRS:{schema:{}}});B.extend(A,B.Plugin.Base,{initializer:function(C){this.doBefore("_defDataFn",this._beforeDefDataFn);},_beforeDefDataFn:function(E){var D=(B.DataSource.IO&&(this.get("host") instanceof B.DataSource.IO)&&B.Lang.isString(E.data.responseText))?E.data.responseText:E.data,C=B.DataSchema.Array.apply(this.get("schema"),D);if(!C){C={meta:{},results:D};}this.get("host").fire("response",B.mix({response:C},E));return new B.Do.Halt("DataSourceArraySchema plugin halted _defDataFn");}});B.namespace("Plugin").DataSourceArraySchema=A;},"3.0.0",{requires:["plugin","datasource-local","dataschema-array"]});

View File

@@ -0,0 +1,113 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('datasource-arrayschema', function(Y) {
/**
* Extends DataSource with schema-parsing on array data.
*
* @module datasource
* @submodule datasource-arrayschema
*/
/**
* Adds schema-parsing to the DataSource Utility.
* @class DataSourceArraySchema
* @extends Plugin.Base
*/
var DataSourceArraySchema = function() {
DataSourceArraySchema.superclass.constructor.apply(this, arguments);
};
Y.mix(DataSourceArraySchema, {
/**
* The namespace for the plugin. This will be the property on the host which
* references the plugin instance.
*
* @property NS
* @type String
* @static
* @final
* @value "schema"
*/
NS: "schema",
/**
* Class name.
*
* @property NAME
* @type String
* @static
* @final
* @value "dataSourceArraySchema"
*/
NAME: "dataSourceArraySchema",
/////////////////////////////////////////////////////////////////////////////
//
// DataSourceArraySchema Attributes
//
/////////////////////////////////////////////////////////////////////////////
ATTRS: {
schema: {
//value: {}
}
}
});
Y.extend(DataSourceArraySchema, Y.Plugin.Base, {
/**
* Internal init() handler.
*
* @method initializer
* @param config {Object} Config object.
* @private
*/
initializer: function(config) {
this.doBefore("_defDataFn", this._beforeDefDataFn);
},
/**
* Parses raw data into a normalized response.
*
* @method _beforeDefDataFn
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>data (Object)</dt> <dd>Raw data.</dd>
* </dl>
* @protected
*/
_beforeDefDataFn: function(e) {
var data = (Y.DataSource.IO && (this.get("host") instanceof Y.DataSource.IO) && Y.Lang.isString(e.data.responseText)) ? e.data.responseText : e.data,
response = Y.DataSchema.Array.apply(this.get("schema"), data);
// Default
if(!response) {
response = {
meta: {},
results: data
};
}
this.get("host").fire("response", Y.mix({response:response}, e));
return new Y.Do.Halt("DataSourceArraySchema plugin halted _defDataFn");
}
});
Y.namespace('Plugin').DataSourceArraySchema = DataSourceArraySchema;
}, '3.0.0' ,{requires:['plugin', 'datasource-local', 'dataschema-array']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("datasource-cache",function(B){var A=function(){A.superclass.constructor.apply(this,arguments);};B.mix(A,{NS:"cache",NAME:"dataSourceCache",ATTRS:{}});B.extend(A,B.Cache,{initializer:function(C){this.doBefore("_defRequestFn",this._beforeDefRequestFn);this.doBefore("_defResponseFn",this._beforeDefResponseFn);},_beforeDefRequestFn:function(D){var C=(this.retrieve(D.request))||null;if(C&&C.response){this.get("host").fire("response",B.mix({response:C.response},D));return new B.Do.Halt("DataSourceCache plugin halted _defRequestFn");}},_beforeDefResponseFn:function(C){if(C.response&&!C.response.cached){C.response.cached=true;this.add(C.request,C.response,(C.callback&&C.callback.argument));}}});B.namespace("Plugin").DataSourceCache=A;},"3.0.0",{requires:["datasource-local","cache"]});

View File

@@ -0,0 +1,136 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('datasource-cache', function(Y) {
/**
* Extends DataSource with caching functionality.
*
* @module datasource
* @submodule datasource-cache
*/
/**
* Adds cacheability to the DataSource Utility.
* @class DataSourceCache
* @extends Cache
*/
var DataSourceCache = function() {
DataSourceCache.superclass.constructor.apply(this, arguments);
};
Y.mix(DataSourceCache, {
/**
* The namespace for the plugin. This will be the property on the host which
* references the plugin instance.
*
* @property NS
* @type String
* @static
* @final
* @value "cache"
*/
NS: "cache",
/**
* Class name.
*
* @property NAME
* @type String
* @static
* @final
* @value "dataSourceCache"
*/
NAME: "dataSourceCache",
/////////////////////////////////////////////////////////////////////////////
//
// DataSourceCache Attributes
//
/////////////////////////////////////////////////////////////////////////////
ATTRS: {
}
});
Y.extend(DataSourceCache, Y.Cache, {
/**
* Internal init() handler.
*
* @method initializer
* @param config {Object} Config object.
* @private
*/
initializer: function(config) {
this.doBefore("_defRequestFn", this._beforeDefRequestFn);
this.doBefore("_defResponseFn", this._beforeDefResponseFn);
},
/**
* First look for cached response, then send request to live data.
*
* @method _beforeDefRequestFn
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object.</dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* </dl>
* @protected
*/
_beforeDefRequestFn: function(e) {
// Is response already in the Cache?
var entry = (this.retrieve(e.request)) || null;
if(entry && entry.response) {
this.get("host").fire("response", Y.mix({response: entry.response}, e));
return new Y.Do.Halt("DataSourceCache plugin halted _defRequestFn");
}
},
/**
* Adds data to cache before returning data.
*
* @method _beforeDefResponseFn
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>data (Object)</dt> <dd>Raw data.</dd>
* <dt>response (Object)</dt> <dd>Normalized response object with the following properties:
* <dl>
* <dt>cached (Object)</dt> <dd>True when response is cached.</dd>
* <dt>results (Object)</dt> <dd>Parsed results.</dd>
* <dt>meta (Object)</dt> <dd>Parsed meta data.</dd>
* <dt>error (Object)</dt> <dd>Error object.</dd>
* </dl>
* </dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* </dl>
* @protected
*/
_beforeDefResponseFn: function(e) {
// Add to Cache before returning
if(e.response && !e.response.cached) {
e.response.cached = true;
this.add(e.request, e.response, (e.callback && e.callback.argument));
}
}
});
Y.namespace('Plugin').DataSourceCache = DataSourceCache;
}, '3.0.0' ,{requires:['datasource-local', 'cache']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("datasource-function",function(B){var A=B.Lang,C=function(){C.superclass.constructor.apply(this,arguments);};B.mix(C,{NAME:"dataSourceFunction",ATTRS:{source:{validator:A.isFunction}}});B.extend(C,B.DataSource.Local,{_defRequestFn:function(G){var F=this.get("source"),D;if(F){try{D=F(G.request,this,G);this.fire("data",B.mix({data:D},G));}catch(E){G.error=E;this.fire("error",G);}}else{G.error=new Error("Function data failure");this.fire("error",G);}return G.tId;}});B.DataSource.Function=C;},"3.0.0",{requires:["datasource-local"]});

View File

@@ -0,0 +1,115 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('datasource-function', function(Y) {
/**
* Provides a DataSource implementation which can be used to retrieve data from a custom function.
*
* @module datasource
* @submodule datasource-function
*/
/**
* Function subclass for the DataSource Utility.
* @class DataSource.Function
* @extends DataSource.Local
* @constructor
*/
var LANG = Y.Lang,
DSFn = function() {
DSFn.superclass.constructor.apply(this, arguments);
};
/////////////////////////////////////////////////////////////////////////////
//
// DataSource.Function static properties
//
/////////////////////////////////////////////////////////////////////////////
Y.mix(DSFn, {
/**
* Class name.
*
* @property NAME
* @type String
* @static
* @final
* @value "dataSourceFunction"
*/
NAME: "dataSourceFunction",
/////////////////////////////////////////////////////////////////////////////
//
// DataSource.Function Attributes
//
/////////////////////////////////////////////////////////////////////////////
ATTRS: {
/**
* @attribute source
* @description Pointer to live data.
* @type MIXED
* @default null
*/
source: {
validator: LANG.isFunction
}
}
});
Y.extend(DSFn, Y.DataSource.Local, {
/**
* Passes query string to IO. Fires <code>response</code> event when
* response is received asynchronously.
*
* @method _defRequestFn
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* </dl>
* @protected
*/
_defRequestFn: function(e) {
var fn = this.get("source"),
response;
if(fn) {
try {
response = fn(e.request, this, e);
this.fire("data", Y.mix({data:response}, e));
}
catch(error) {
e.error = error;
this.fire("error", e);
}
}
else {
e.error = new Error("Function data failure");
this.fire("error", e);
}
return e.tId;
}
});
Y.DataSource.Function = DSFn;
}, '3.0.0' ,{requires:['datasource-local']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("datasource-get",function(B){var A=function(){A.superclass.constructor.apply(this,arguments);};B.mix(A,{NAME:"dataSourceGet",ATTRS:{get:{value:B.Get,cloneDefaultValue:false},asyncMode:{value:"allowAll"},scriptCallbackParam:{value:"callback"},generateRequestCallback:{value:function(C,D){return"&"+C.get("scriptCallbackParam")+"=YUI.Env.DataSource.callbacks["+D+"]";}}},callbacks:[],_tId:0});B.extend(A,B.DataSource.Local,{_defRequestFn:function(F){var E=this.get("source"),D=this.get("get"),G=A._tId++,C=this;YUI.Env.DataSource.callbacks[G]=B.rbind(function(H){if((C.get("asyncMode")!=="ignoreStaleResponses")||(G===A.callbacks.length-1)){C.fire("data",B.mix({data:H},F));}else{}delete A.callbacks[G];},this,G);E+=F.request+this.get("generateRequestCallback")(this,G);D.script(E,{autopurge:true,onFailure:B.bind(function(H){H.error=new Error("Script node data failure");this.fire("error",H);},this,F)});return F.tId;}});B.DataSource.Get=A;YUI.namespace("Env.DataSource.callbacks");},"3.0.0",{requires:["datasource-local","get"]});

View File

@@ -0,0 +1,226 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('datasource-get', function(Y) {
/**
* Provides a DataSource implementation which can be used to retrieve data via the Get Utility.
*
* @module datasource
* @submodule datasource-get
*/
/**
* Get Utility subclass for the DataSource Utility.
* @class DataSource.Get
* @extends DataSource.Local
* @constructor
*/
var DSGet = function() {
DSGet.superclass.constructor.apply(this, arguments);
};
/////////////////////////////////////////////////////////////////////////////
//
// DataSource.Get static properties
//
/////////////////////////////////////////////////////////////////////////////
Y.mix(DSGet, {
/**
* Class name.
*
* @property NAME
* @type String
* @static
* @final
* @value "dataSourceGet"
*/
NAME: "dataSourceGet",
/////////////////////////////////////////////////////////////////////////////
//
// DataSource.Get Attributes
//
/////////////////////////////////////////////////////////////////////////////
ATTRS: {
/**
* Pointer to Get Utility.
*
* @attribute get
* @type Y.Get
* @default Y.Get
*/
get: {
value: Y.Get,
cloneDefaultValue: false
},
/**
* Defines request/response management in the following manner:
* <dl>
* <!--<dt>queueRequests</dt>
* <dd>If a request is already in progress, wait until response is returned before sending the next request.</dd>
* <dt>cancelStaleRequests</dt>
* <dd>If a request is already in progress, cancel it before sending the next request.</dd>-->
* <dt>ignoreStaleResponses</dt>
* <dd>Send all requests, but handle only the response for the most recently sent request.</dd>
* <dt>allowAll</dt>
* <dd>Send all requests and handle all responses.</dd>
* </dl>
*
* @attribute asyncMode
* @type String
* @default "allowAll"
*/
asyncMode: {
value: "allowAll"
},
/**
* Callback string parameter name sent to the remote script. By default,
* requests are sent to
* &#60;URI&#62;?&#60;scriptCallbackParam&#62;=callbackFunction
*
* @attribute scriptCallbackParam
* @type String
* @default "callback"
*/
scriptCallbackParam : {
value: "callback"
},
/**
* Accepts the DataSource instance and a callback ID, and returns a callback
* param/value string that gets appended to the script URI. Implementers
* can customize this string to match their server's query syntax.
*
* @attribute generateRequestCallback
* @type Function
*/
generateRequestCallback : {
value: function(self, id) {
return "&" + self.get("scriptCallbackParam") + "=YUI.Env.DataSource.callbacks["+id+"]" ;
}
}
},
/**
* Global array of callback functions, one for each request sent.
*
* @property callbacks
* @type Function[]
* @static
*/
callbacks : [],
/**
* Unique ID to track requests.
*
* @property _tId
* @type Number
* @private
* @static
*/
_tId : 0
});
Y.extend(DSGet, Y.DataSource.Local, {
/**
* Passes query string to Get Utility. Fires <code>response</code> event when
* response is received asynchronously.
*
* @method _defRequestFn
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* </dl>
* @protected
*/
_defRequestFn: function(e) {
var uri = this.get("source"),
get = this.get("get"),
id = DSGet._tId++,
self = this;
// Dynamically add handler function with a closure to the callback stack
YUI.Env.DataSource.callbacks[id] = Y.rbind(function(response) {
if((self.get("asyncMode") !== "ignoreStaleResponses")||
(id === DSGet.callbacks.length-1)) { // Must ignore stale responses
self.fire("data", Y.mix({data:response}, e));
}
else {
}
delete DSGet.callbacks[id];
}, this, id);
// We are now creating a request
uri += e.request + this.get("generateRequestCallback")(this, id);
//uri = this.doBefore(sUri);
get.script(uri, {
autopurge: true,
// Works in Firefox only....
onFailure: Y.bind(function(e) {
e.error = new Error("Script node data failure");
this.fire("error", e);
}, this, e)
});
return e.tId;
}
});
Y.DataSource.Get = DSGet;
YUI.namespace("Env.DataSource.callbacks");
}, '3.0.0' ,{requires:['datasource-local', 'get']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("datasource-io",function(B){var A=function(){A.superclass.constructor.apply(this,arguments);};B.mix(A,{NAME:"dataSourceIO",ATTRS:{io:{value:B.io,cloneDefaultValue:false}}});B.extend(A,B.DataSource.Local,{initializer:function(C){this._queue={interval:null,conn:null,requests:[]};},_queue:null,_defRequestFn:function(F){var E=this.get("source"),G=this.get("io"),D=F.request,C=B.mix(F.cfg,{on:{success:function(J,H,I){this.fire("data",B.mix({data:H},I));},failure:function(J,H,I){I.error=new Error("IO data failure");this.fire("error",B.mix({data:H},I));this.fire("data",B.mix({data:H},I));}},context:this,arguments:F});if(B.Lang.isString(D)){if(C.method&&(C.method.toUpperCase()==="POST")){C.data=C.data?C.data+D:D;}else{E+=D;}}G(E,C);return F.tId;}});B.DataSource.IO=A;},"3.0.0",{requires:["datasource-local","io"]});

View File

@@ -0,0 +1,154 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('datasource-io', function(Y) {
/**
* Provides a DataSource implementation which can be used to retrieve data via the IO Utility.
*
* @module datasource
* @submodule datasource-io
*/
/**
* IO subclass for the DataSource Utility.
* @class DataSource.IO
* @extends DataSource.Local
* @constructor
*/
var DSIO = function() {
DSIO.superclass.constructor.apply(this, arguments);
};
/////////////////////////////////////////////////////////////////////////////
//
// DataSource.IO static properties
//
/////////////////////////////////////////////////////////////////////////////
Y.mix(DSIO, {
/**
* Class name.
*
* @property NAME
* @type String
* @static
* @final
* @value "dataSourceIO"
*/
NAME: "dataSourceIO",
/////////////////////////////////////////////////////////////////////////////
//
// DataSource.IO Attributes
//
/////////////////////////////////////////////////////////////////////////////
ATTRS: {
/**
* Pointer to IO Utility.
*
* @attribute io
* @type Y.io
* @default Y.io
*/
io: {
value: Y.io,
cloneDefaultValue: false
}
}
});
Y.extend(DSIO, Y.DataSource.Local, {
/**
* Internal init() handler.
*
* @method initializer
* @param config {Object} Config object.
* @private
*/
initializer: function(config) {
this._queue = {interval:null, conn:null, requests:[]};
},
/**
* @property _queue
* @description Object literal to manage asynchronous request/response
* cycles enabled if queue needs to be managed (asyncMode/ioConnMode):
* <dl>
* <dt>interval {Number}</dt>
* <dd>Interval ID of in-progress queue.</dd>
* <dt>conn</dt>
* <dd>In-progress connection identifier (if applicable).</dd>
* <dt>requests {Object[]}</dt>
* <dd>Array of queued request objects: {request:request, callback:callback}.</dd>
* </dl>
* @type Object
* @default {interval:null, conn:null, requests:[]}
* @private
*/
_queue: null,
/**
* Passes query string to IO. Fires <code>response</code> event when
* response is received asynchronously.
*
* @method _defRequestFn
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* </dl>
* @protected
*/
_defRequestFn: function(e) {
var uri = this.get("source"),
io = this.get("io"),
request = e.request,
cfg = Y.mix(e.cfg, {
on: {
success: function (id, response, e) {
this.fire("data", Y.mix({data:response}, e));
},
failure: function (id, response, e) {
e.error = new Error("IO data failure");
this.fire("error", Y.mix({data:response}, e));
this.fire("data", Y.mix({data:response}, e));
}
},
context: this,
arguments: e
});
// Support for POST transactions
if(Y.Lang.isString(request)) {
if(cfg.method && (cfg.method.toUpperCase() === "POST")) {
cfg.data = cfg.data ? cfg.data+request : request;
}
else {
uri += request;
}
}
io(uri, cfg);
return e.tId;
}
});
Y.DataSource.IO = DSIO;
}, '3.0.0' ,{requires:['datasource-local', 'io']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("datasource-jsonschema",function(B){var A=function(){A.superclass.constructor.apply(this,arguments);};B.mix(A,{NS:"schema",NAME:"dataSourceJSONSchema",ATTRS:{schema:{}}});B.extend(A,B.Plugin.Base,{initializer:function(C){this.doBefore("_defDataFn",this._beforeDefDataFn);},_beforeDefDataFn:function(E){var D=(B.DataSource.IO&&(this.get("host") instanceof B.DataSource.IO)&&B.Lang.isString(E.data.responseText))?E.data.responseText:E.data,C=B.DataSchema.JSON.apply(this.get("schema"),D);if(!C){C={meta:{},results:D};}this.get("host").fire("response",B.mix({response:C},E));return new B.Do.Halt("DataSourceJSONSchema plugin halted _defDataFn");}});B.namespace("Plugin").DataSourceJSONSchema=A;},"3.0.0",{requires:["plugin","datasource-local","dataschema-json"]});

View File

@@ -0,0 +1,113 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('datasource-jsonschema', function(Y) {
/**
* Extends DataSource with schema-parsing on JSON data.
*
* @module datasource
* @submodule datasource-jsonschema
*/
/**
* Adds schema-parsing to the DataSource Utility.
* @class DataSourceJSONSchema
* @extends Plugin.Base
*/
var DataSourceJSONSchema = function() {
DataSourceJSONSchema.superclass.constructor.apply(this, arguments);
};
Y.mix(DataSourceJSONSchema, {
/**
* The namespace for the plugin. This will be the property on the host which
* references the plugin instance.
*
* @property NS
* @type String
* @static
* @final
* @value "schema"
*/
NS: "schema",
/**
* Class name.
*
* @property NAME
* @type String
* @static
* @final
* @value "dataSourceJSONSchema"
*/
NAME: "dataSourceJSONSchema",
/////////////////////////////////////////////////////////////////////////////
//
// DataSourceJSONSchema Attributes
//
/////////////////////////////////////////////////////////////////////////////
ATTRS: {
schema: {
//value: {}
}
}
});
Y.extend(DataSourceJSONSchema, Y.Plugin.Base, {
/**
* Internal init() handler.
*
* @method initializer
* @param config {Object} Config object.
* @private
*/
initializer: function(config) {
this.doBefore("_defDataFn", this._beforeDefDataFn);
},
/**
* Parses raw data into a normalized response.
*
* @method _beforeDefDataFn
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>data (Object)</dt> <dd>Raw data.</dd>
* </dl>
* @protected
*/
_beforeDefDataFn: function(e) {
var data = (Y.DataSource.IO && (this.get("host") instanceof Y.DataSource.IO) && Y.Lang.isString(e.data.responseText)) ? e.data.responseText : e.data,
response = Y.DataSchema.JSON.apply(this.get("schema"), data);
// Default
if(!response) {
response = {
meta: {},
results: data
};
}
this.get("host").fire("response", Y.mix({response:response}, e));
return new Y.Do.Halt("DataSourceJSONSchema plugin halted _defDataFn");
}
});
Y.namespace('Plugin').DataSourceJSONSchema = DataSourceJSONSchema;
}, '3.0.0' ,{requires:['plugin', 'datasource-local', 'dataschema-json']});

View File

@@ -0,0 +1,8 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add("datasource-local",function(C){var B=C.Lang,A=function(){A.superclass.constructor.apply(this,arguments);};C.mix(A,{NAME:"dataSourceLocal",ATTRS:{source:{value:null}},_tId:0,issueCallback:function(E){if(E.callback){var D=(E.error&&E.callback.failure)||E.callback.success;if(D){D(E);}}}});C.extend(A,C.Base,{initializer:function(D){this._initEvents();},_initEvents:function(){this.publish("request",{defaultFn:C.bind("_defRequestFn",this),queuable:true});this.publish("data",{defaultFn:C.bind("_defDataFn",this),queuable:true});this.publish("response",{defaultFn:C.bind("_defResponseFn",this),queuable:true});},_defRequestFn:function(E){var D=this.get("source");if(B.isUndefined(D)){E.error=new Error("Local source undefined");}if(E.error){this.fire("error",E);}this.fire("data",C.mix({data:D},E));},_defDataFn:function(G){var E=G.data,F=G.meta,D={results:(B.isArray(E))?E:[E],meta:(F)?F:{}};this.fire("response",C.mix({response:D},G));},_defResponseFn:function(D){A.issueCallback(D);},sendRequest:function(E,G,D){var F=A._tId++;this.fire("request",{tId:F,request:E,callback:G,cfg:D||{}});return F;}});C.namespace("DataSource").Local=A;},"3.0.0",{requires:["base"]});

View File

@@ -0,0 +1,336 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 3.0.0
build: 1549
*/
YUI.add('datasource-local', function(Y) {
/**
* The DataSource utility provides a common configurable interface for widgets to
* access a variety of data, from JavaScript arrays to online database servers.
*
* @module datasource
*/
/**
* Provides the base DataSource implementation, which can be extended to
* create DataSources for specific data protocols, such as the IO Utility, the
* Get Utility, or custom functions.
*
* @module datasource
* @submodule datasource-local
*/
/**
* Base class for the DataSource Utility.
* @class DataSource.Local
* @extends Base
* @constructor
*/
var LANG = Y.Lang,
DSLocal = function() {
DSLocal.superclass.constructor.apply(this, arguments);
};
/////////////////////////////////////////////////////////////////////////////
//
// DataSource static properties
//
/////////////////////////////////////////////////////////////////////////////
Y.mix(DSLocal, {
/**
* Class name.
*
* @property NAME
* @type String
* @static
* @final
* @value "dataSourceLocal"
*/
NAME: "dataSourceLocal",
/////////////////////////////////////////////////////////////////////////////
//
// DataSource Attributes
//
/////////////////////////////////////////////////////////////////////////////
ATTRS: {
/**
* @attribute source
* @description Pointer to live data.
* @type MIXED
* @default null
*/
source: {
value: null
}
},
/**
* Global transaction counter.
*
* @property DataSource._tId
* @type Number
* @static
* @private
* @default 0
*/
_tId: 0,
/**
* Executes a given callback. The third param determines whether to execute
*
* @method DataSource.issueCallback
* @param callback {Object} The callback object.
* @param params {Array} params to be passed to the callback method
* @param error {Boolean} whether an error occurred
* @static
*/
issueCallback: function (e) {
if(e.callback) {
var callbackFunc = (e.error && e.callback.failure) || e.callback.success;
if (callbackFunc) {
callbackFunc(e);
}
}
}
});
Y.extend(DSLocal, Y.Base, {
/**
* Internal init() handler.
*
* @method initializer
* @param config {Object} Config object.
* @private
*/
initializer: function(config) {
this._initEvents();
},
/**
* This method creates all the events for this module.
* @method _initEvents
* @private
*/
_initEvents: function() {
/**
* Fired when a data request is received.
*
* @event request
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object.</dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* </dl>
* @preventable _defRequestFn
*/
this.publish("request", {defaultFn: Y.bind("_defRequestFn", this), queuable:true});
/**
* Fired when raw data is received.
*
* @event data
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* <dt>data (Object)</dt> <dd>Raw data.</dd>
* </dl>
* @preventable _defDataFn
*/
this.publish("data", {defaultFn: Y.bind("_defDataFn", this), queuable:true});
/**
* Fired when response is returned.
*
* @event response
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* <dt>data (Object)</dt> <dd>Raw data.</dd>
* <dt>response (Object)</dt> <dd>Normalized response object with the following properties:
* <dl>
* <dt>results (Object)</dt> <dd>Parsed results.</dd>
* <dt>meta (Object)</dt> <dd>Parsed meta data.</dd>
* <dt>error (Boolean)</dt> <dd>Error flag.</dd>
* </dl>
* </dd>
* </dl>
* @preventable _defResponseFn
*/
this.publish("response", {defaultFn: Y.bind("_defResponseFn", this), queuable:true});
/**
* Fired when an error is encountered.
*
* @event error
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* <dt>data (Object)</dt> <dd>Raw data.</dd>
* <dt>response (Object)</dt> <dd>Normalized response object with the following properties:
* <dl>
* <dt>results (Object)</dt> <dd>Parsed results.</dd>
* <dt>meta (Object)</dt> <dd>Parsed meta data.</dd>
* <dt>error (Object)</dt> <dd>Error object.</dd>
* </dl>
* </dd>
* </dl>
*/
},
/**
* Manages request/response transaction. Must fire <code>response</code>
* event when response is received. This method should be implemented by
* subclasses to achieve more complex behavior such as accessing remote data.
*
* @method _defRequestFn
* @param e {Event.Facade} Event Facadewith the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* </dl>
* @protected
*/
_defRequestFn: function(e) {
var data = this.get("source");
// Problematic data
if(LANG.isUndefined(data)) {
e.error = new Error("Local source undefined");
}
if(e.error) {
this.fire("error", e);
}
this.fire("data", Y.mix({data:data}, e));
},
/**
* Normalizes raw data into a response that includes results and meta properties.
*
* @method _defDataFn
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* <dt>data (Object)</dt> <dd>Raw data.</dd>
* </dl>
* @protected
*/
_defDataFn: function(e) {
var data = e.data,
meta = e.meta,
response = {
results: (LANG.isArray(data)) ? data : [data],
meta: (meta) ? meta : {}
};
this.fire("response", Y.mix({response: response}, e));
},
/**
* Sends data as a normalized response to callback.
*
* @method _defResponseFn
* @param e {Event.Facade} Event Facade with the following properties:
* <dl>
* <dt>tId (Number)</dt> <dd>Unique transaction ID.</dd>
* <dt>request (Object)</dt> <dd>The request.</dd>
* <dt>callback (Object)</dt> <dd>The callback object with the following properties:
* <dl>
* <dt>success (Function)</dt> <dd>Success handler.</dd>
* <dt>failure (Function)</dt> <dd>Failure handler.</dd>
* </dl>
* </dd>
* <dt>cfg (Object)</dt> <dd>Configuration object.</dd>
* <dt>data (Object)</dt> <dd>Raw data.</dd>
* <dt>response (Object)</dt> <dd>Normalized response object with the following properties:
* <dl>
* <dt>results (Object)</dt> <dd>Parsed results.</dd>
* <dt>meta (Object)</dt> <dd>Parsed meta data.</dd>
* <dt>error (Boolean)</dt> <dd>Error flag.</dd>
* </dl>
* </dd>
* </dl>
* @protected
*/
_defResponseFn: function(e) {
// Send the response back to the callback
DSLocal.issueCallback(e);
},
/**
* Generates a unique transaction ID and fires <code>request</code> event.
*
* @method sendRequest
* @param request {Object} Request.
* @param callback {Object} An object literal with the following properties:
* <dl>
* <dt><code>success</code></dt>
* <dd>The function to call when the data is ready.</dd>
* <dt><code>failure</code></dt>
* <dd>The function to call upon a response failure condition.</dd>
* <dt><code>argument</code></dt>
* <dd>Arbitrary data payload that will be passed back to the success and failure handlers.</dd>
* </dl>
* @param cfg {Object} Configuration object
* @return {Number} Transaction ID.
*/
sendRequest: function(request, callback, cfg) {
var tId = DSLocal._tId++;
this.fire("request", {tId:tId, request:request, callback:callback, cfg:cfg || {}});
return tId;
}
});
Y.namespace("DataSource").Local = DSLocal;
}, '3.0.0' ,{requires:['base']});

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More