/************************************************************************** * Licensed Materials - Property of IBM * * * * IBM Cognos Products: AGS * * * * (C) Copyright IBM Corp. 2005, 2018 * * * * US Government Users Restricted Rights - Use, duplication or disclosure * * restricted by GSA ADP Schedule Contract with IBM Corp. * **************************************************************************/ var cf = parent.getConfigFrame(); // information about a dropZone function DropZone(id, menuString, defaultText, updateAgentItems, tab_id,overwrite,allowFunctionsAndParams,elementProcessor){ this.id = id; this.tab_id = tab_id; this.menuString = menuString; this.defaultText = defaultText; this.updateAgentItems = updateAgentItems; this.overwrite = overwrite; this.allowFunctionsAndParams = allowFunctionsAndParams; this.elementProcessor = elementProcessor; } function DropZoneHandler() { // save some values this.registeredObjectsIndex = new Object(); } // export save the id of the element that we're inserting into DropZoneHandler.prototype.saveId = function(id) { this.id = id; } //this method is for dynamicly named groups of dropzones, that may have implicit agent item deletion //if one of them vanishes DropZoneHandler.prototype.registerDropZoneGroup = function(dropzones, dropzone_group_id) { var fields = new Array(); for(var i = 0; dropzones && dropzones.length && i < dropzones.length; i++) { //this will probably have been made already in the normal register dropzone method var fieldContent = parent.getAgentItemsListener().getFieldContent(dropzones[i].id, dropzone_group_id); //field content not vital for hte drop zone group members fields.push(fieldContent ? fieldContent : new parent.FieldContent(dropzones[i].id, dropzone_group_id, "")); } parent.getAgentItemsListener().registerDynamicGroup(fields, dropzone_group_id, window.name); } //handy method to use the new Dropzone object //cant overload in script... so use new name DropZoneHandler.prototype.registerDropZoneObject = function(dropzone) { this.registerDropZone(dropzone.id, dropzone.menuString, dropzone.defaultText, dropzone.updateAgentItems, dropzone.tab_id,dropzone.overwrite,dropzone.allowFunctionsAndParams,dropzone.elementProcessor); } //check the id is a dropzone DropZoneHandler.prototype.isDropZone = function(anId) { return (this.registeredObjectsIndex[anId] && this.registeredObjectsIndex[anId] != 'undefined'); } //check the id is a dropzone and if so is it one that overwrites entries with a drop DropZoneHandler.prototype.isOverWrite = function(anId) { return (this.registeredObjectsIndex[anId] && this.registeredObjectsIndex[anId].overwrite && this.registeredObjectsIndex[anId].overwrite == true); } // set the following methods as part of the dropZoneHandler DropZoneHandler.prototype.registerDropZone = function(id, menuString, defaultText, updateAgentItems, task_id, overwrite, allowFunctionsAndParams,elementProcessor){ if (document.forms[0] != null) { // create the onsubmit handler if (!this.registeredObjectsIndex.submit) { this.registeredObjectsIndex.submit = document.forms[0].submit; document.forms[0].submit = submitHandler; } } attachDropEvents(id); this.registeredObjectsIndex[id] = elementProcessor; // create an entry in the registeredObjectsIndex if (!this.registeredObjectsIndex[id] || this.registeredObjectsIndex[id] == 'undefined') { elementProcessor = new ElementProcessor(id,defaultText,overwrite); this.registeredObjectsIndex[id] = elementProcessor; } if (allowFunctionsAndParams && allowFunctionsAndParams != 'undefined' && allowFunctionsAndParams != '') { elementProcessor.allowFunctionsAndParams = allowFunctionsAndParams; } if (updateAgentItems && updateAgentItems != 'undefined' && updateAgentItems != '') { elementProcessor.updateAgentItems = updateAgentItems; } if (elementProcessor.isEmpty && (typeof elementProcessor.isEmpty === "function") && elementProcessor.isEmpty()) { elementProcessor.setDefaultValue(); } //register for manual agent item deletion parent.getAgentItemsListener().registerField(id, task_id, elementProcessor.getElementValue(), window.name); } DropZoneHandler.prototype.registerPreEventHandler = function(id, event, func) { var registeredObject = this.registeredObjectsIndex[id]; registeredObject["pre" + event] = func; } DropZoneHandler.prototype.registerPostEventHandler = function(id, event, func) { var registeredObject = this.registeredObjectsIndex[id]; registeredObject["post" + event] = func; } DropZoneHandler.prototype.registerDropHandler = function(id, func) { var registeredObject = this.registeredObjectsIndex[id]; registeredObject["dropfunc"] = func; } DropZoneHandler.prototype.registerUpdateValueHandler = function(id, func) { var registeredObject = this.registeredObjectsIndex[id]; registeredObject["updatevaluefunc"] = func; } DropZoneHandler.prototype.handleSubmit = function(event) { // loop over all the value that we've got registered for (var id in this.registeredObjectsIndex) { var registeredObject = this.registeredObjectsIndex[id]; if (registeredObject.removeDefaultValue) { // set to nothing registeredObject.removeDefaultValue(); } } // call the correct function var submit_function = this.registeredObjectsIndex.submit; // give this back to the form object document.forms[0].submit = submit_function; // now call submit on the form document.forms[0].submit(); } DropZoneHandler.prototype.handleOnDragOver = function(event) { // have to create a textRange for the entity var id = parent.agsFormUtils.getEventId(event); var srcElem = parent.agsFormUtils.getElementByIdOrName(id); var tagName = srcElem?srcElem.tagName:""; var registeredObject = this.registeredObjectsIndex[id]; //Make sure we are dropping into an element we have registered if (!registeredObject || registeredObject.tagName != tagName) { return; } // if we're in default mode then do nothing registeredObject.setDropLocation(event); // have to prevent the default handling event.returnValue = false; } DropZoneHandler.prototype.handleOnDragEnter = function(event) { // set the cursor shape event.dataTransfer.dropEffect="move"; // have to prevent the default handling event.returnValue = false; } DropZoneHandler.prototype.handleCancelDefault = function(event) { // just override the default handling of the drag event.returnValue = false; } /** * This function will take a given id and set it as the * default droppable one and then insert into it. * If id is not defined we use the already saved one. */ DropZoneHandler.prototype.handleInsert = function(id) { //We have an id so use it. if (id && id != 'undefined') { this.saveId(id); } //Make sure we have an element id that we may have visited. if (this.id && this.id != 'undefined') { this.handleDrop(null); } } DropZoneHandler.prototype.handleDrop = function(event) { //check that drag originated from tree. if (!cf.cfgGet("selectedTreeNodes")) { return; } // it's possible that we're dropping into more than a single // frame - and yet the correct drop handler is called cause it's // attached to the individual elements in the frames - so save the // frame that we're dropping into cf.dropFrame = window.name; // get the id of the element that we're dropping into //IE calls the ondrop event before the onfocus. // get the id of the element that we're dropping into //if no event then we use the id, this is to handle the insert var id = event && event != 'undefined'?parent.agsFormUtils.getEventId(event):this.id; //Save it for later usage. this.saveId(id); var registeredObject = this.registeredObjectsIndex[id]; if (registeredObject["preondrop"] != null) { registeredObject["preondrop"](); } this.process(); if (registeredObject["postondrop"] != null) { registeredObject["postondrop"](); } if (registeredObject.isEmpty()) { // check to make sure something was entered // set the default value registeredObject.setDefaultValue(); } } DropZoneHandler.prototype.handleOnFocus = function(event) { // it's possible that we're dropping into more than a single // frame - and yet the correct drop handler is called cause it's // attached to the individual elements in the frames - so save the // frame that we're dropping into cf.dropFrame = window.name; // get the id of the element that got the focus // get the id of the element that we're dropping into var id = parent.agsFormUtils.getEventId(event); //hang on to this so that the double click insert from meta data tree knows what to insert to this.saveId(id); var registeredObject = this.registeredObjectsIndex[id]; if (registeredObject["preonfocus"] != null) { registeredObject["preonfocus"](); } registeredObject.removeDefaultValue(); if (registeredObject["postonfocus"] != null) { registeredObject["postonfocus"](); } // stop the event propogation event.cancelBubble = true; } DropZoneHandler.prototype.handleOnBlur = function(event) { // get the id of the element that we're leaving var id = parent.agsFormUtils.getEventId(event); var registeredObject = this.registeredObjectsIndex[id]; if (registeredObject["preonblur"] != null) { registeredObject["preonblur"](id); } // if we do not have a default value there at the moment, then set it if (registeredObject.isEmpty()) { registeredObject.setDefaultValue(); } if (registeredObject["postonblur"] != null) { registeredObject["postonblur"](id); } // put this here - the post on blur handler the ability to alter the contents // of the field - so we have to wait till right at the last moment to check // the contents of the field. parent.getAgentItemsListener().updateField(id, this.getElementValue(id)); } DropZoneHandler.prototype.process = function(item) { if (!this.id || this.id == 'undefined') { return; } // get the registered object if there is one var registeredObject = this.registeredObjectsIndex[this.id]; var selectedNodesHolder = cf.cfgGet("selectedTreeNodes"); var allowDrop = selectedNodesHolder.containsFunctions || selectedNodesHolder.containsParams; if (!registeredObject || !isFocusable(registeredObject.element) || (!registeredObject.allowFunctionsAndParams && allowDrop)) { return; } //this causes the action listener to roll all edits into one reversable action cf.getRedoUndoManager().startEditActionBatch(); // get what we want to drop var dropText = processSelectedNodes(); //Nothing to drop. if (!dropText || dropText.length < 1) { return; } registeredObject.removeDefaultValue(); //This should be removed later on. The caller should create its own //drop thingy that will regsietered and used by drop zone handler. //For now keep the same functionality if (registeredObject["dropfunc"] != null) { // send the data to the function registeredObject["dropfunc"](dropText.join(""),this.id); } else { registeredObject.process(dropText); } cf.getRedoUndoManager().stopEditActionBatch(); } DropZoneHandler.prototype.getDropZoneValue = function(id) { var id = (!id || id == 'undefined')?this.id:id; var registeredObject = this.registeredObjectsIndex[id]; var value = ""; if (registeredObject) { // if it's defaulted if (!registeredObject.isDefaultMode()) { value = registeredObject.getElementValue(); } } return value; } DropZoneHandler.prototype.setDropZoneValue = function(value, id) { var id = (!id || id == 'undefined')?this.id:id; var registeredObject = this.registeredObjectsIndex[id]; // set the value into the object // if it's defaulted if (registeredObject) { // set the value registeredObject.setElementValue(value); } // put this here - update the contents of the field. parent.getAgentItemsListener().updateField(id, this.getElementValue(id)); } DropZoneHandler.prototype.updateDropZoneValue = function(value, id) { var id = (!id || id == 'undefined')?this.id:id; var registeredObject = this.registeredObjectsIndex[id]; // set the value into the object // if it's defaulted if (registeredObject) { // set the value registeredObject.updateElementValue(value); } // put this here - update the contents of the field. parent.getAgentItemsListener().updateField(id, this.getElementValue(id)); cf.agentHasChanged(true); } DropZoneHandler.prototype.setDefault = function(id) { var id = (!id || id == 'undefined')?this.id:id; var registeredObject = this.registeredObjectsIndex[id]; if (registeredObject) { registeredObject.setDefaultValue(); } } DropZoneHandler.prototype.removeDefault = function(id) { var id = (!id || id == 'undefined')?this.id:id; var registeredObject = this.registeredObjectsIndex[id]; if (registeredObject) { registeredObject.removeDefaultValue(); } } DropZoneHandler.prototype.dropZoneDefaulted = function(id) { var id = (!id || id == 'undefined')?this.id:id; var registeredObject = this.registeredObjectsIndex[id]; if (registeredObject != null) { // set the display default flag return registeredObject.isDefaultMode(); } return null; } DropZoneHandler.prototype.updateAgentItems = function(id) { var id = (!id || id == 'undefined')?this.id:id; // check again if (id != null) { var registeredObject = this.registeredObjectsIndex[id]; if (registeredObject != null) { // check to see if we should add to the agent items tree return registeredObject.updateAgentItems; } } return false; } function submitHandler(event) { // forward on to the object droppy.handleSubmit(event); } function dropHandler(event) { // foward on to the object droppy.handleDrop(event); } function cancelDefaultHandler(event) { // forward on to the object droppy.handleCancelDefault(event); } function onDragEnterHandler(event) { // forward to the object droppy.handleOnDragEnter(event); } function onDragOverHandler(event) { // forward to the object droppy.handleOnDragOver(event); } function onFocusHandler(event) { // forward to the object droppy.handleOnFocus(event); } function onBlurHandler(event) { // forward on to the object droppy.handleOnBlur(event); } function attachDropEvents(id) { var element = parent.agsFormUtils.getElementByIdOrName(id);; if (element) { if (cf.browserCheck.isIE5Up()) { element.attachEvent("ondrop",dropHandler); element.attachEvent("ondragenter",onDragEnterHandler); element.attachEvent("ondragover",onDragOverHandler); element.attachEvent("onblur", onBlurHandler); } else if (cf.browserCheck.isNav6Up()) { element.addEventListener("drop",dropHandler,true); element.addEventListener("dragenter",cancelDefaultHandler, true); element.addEventListener("dragover",cancelDefaultHandler, true); element.addEventListener("blur", onBlurHandler, true); } parent.eventHandlerChainUtil.doEventHandlerChain(element, "focus", onFocusHandler); } } /** * Processes selected nodes and returns the drop text. */ function processSelectedNodes() { var dropText = new Array(); var selectedNodesHolder = cf.cfgGet("selectedTreeNodes"); //check that drag originated from tree. if (selectedNodesHolder) { var selectedNodes = selectedNodesHolder.allNodes; //Build the drop text. for (var i = 0; i < selectedNodes.length; i++) { // get the object from the node var obj = selectedNodes[i].getValue(); var type = selectedNodes[i].getNodeTypeObject(); if (obj) { //Get the insert value making sure to get the long or the short name correctly. //Make sure we get the correct drop value. IF we should update agnt Items we need //short name. otherwise it is a long name. //dropText.push(droppy.updateAgentItems()?cf.createDataItemObj(obj.name).getDropValue():obj.getDropValue()); //Is the item we have insertable? if (type.m_oProps.isAgentItemsInsertable() && droppy.updateAgentItems()) { //Insert into data items tree obj = cf.addAgentItem(obj).getValue(); } dropText.push(obj.getDropValue()); //Back to sneakiness..... parent.getAgentItemsListener().addItemToField(droppy.id, obj); } } } return dropText; } /** * Processes selected nodes and returns the drop text. * This functions is used in email_options_ags.xts file which uses the RTE CKEditor */ function processSelectedNodes_ForCKEditorRTE() { var dropText = new Array(); var nodesHolder = new parent.SelectedNodesHolder(); cf.cfgSet("selectedTreeNodes",nodesHolder); var selectedNodesHolder = cf.cfgGet("selectedTreeNodes"); //check that drag originated from tree. if (selectedNodesHolder) { var selectedNodes = selectedNodesHolder.allNodes; //Build the drop text. for (var i = 0; i < selectedNodes.length; i++) { // get the object from the node var obj = selectedNodes[i].getValue(); var type = selectedNodes[i].getNodeTypeObject(); if (obj) { //Get the insert value making sure to get the long or the short name correctly. //Make sure we get the correct drop value. IF we should update agnt Items we need //short name. otherwise it is a long name. //dropText.push(droppy.updateAgentItems()?cf.createDataItemObj(obj.name).getDropValue():obj.getDropValue()); //Is the item we have insertable? if (cf.addAgentItem(obj) != null && cf.addAgentItem(obj).getValue() != null) { obj = cf.addAgentItem(obj).getValue(); } if(obj.getDropValue() != null) { dropText.push(obj.getDropValue()); } //Back to sneakiness..... // parent.getAgentItemsListener().addItemToField(droppy.id, obj); } } } //We are done remove it. cf.cfgRemove("selectedTreeNodes"); return dropText; } DropZoneHandler.prototype.getElementValue = function(id) { var registeredObject = this.registeredObjectsIndex[id]; var srcValue = ""; if (registeredObject) { srcValue = registeredObject.getElementValue(); } return srcValue; } DropZoneHandler.prototype.setElementValue = function(id, value) { var registeredObject = this.registeredObjectsIndex[id]; if (registeredObject) { registeredObject.setElementValue(value); } } DropZoneHandler.prototype.updateElementValue = function(id, value) { var registeredObject = this.registeredObjectsIndex[id]; if (registeredObject) { registeredObject.updateElementValue(value); } } /** * This is to check whether we can set this element to focus. */ function isFocusable(element) { // This is a hack for Mozilla. focus() fails on DIV tags, so we set a custom attribute in the // markup to suppress the focus() check. See suppressionDialog.xts for example. // if (element.getAttribute('focusable')==null) { try { element.focus(); } catch(e) { return false; } } return true; } //check browser version if IE10 function isIE10() { var my_browser = navigator.appName; var b_version = navigator.appVersion; var my_version = b_version.split(";"); var trident_Version = my_version[4]; var version_value = false; if(my_browser == "Microsoft Internet Explorer" && trident_Version >= " Trident/6.0"){ version_value = true; } return version_value; } /** * I recommend that you inherit from this class, if you want to obverride certain * functionality and maintain others. * to do inhertiance here is what you would have to do: * * function myElementProcessor(some param) {some code to define additional and overriden functions} * myElementProcessor.prototype = new ElementProcessor(); * * usage would be: * var a = new myElementProcessor(); * 'a' would contain all the properties of ElementProcessor as well as any overriden and new ones * functions/properties defined by myElementProcessort. */ function ElementProcessor(id,defaultValue,overwrite) { this.id = id; this.element = parent.agsFormUtils.getElementByIdOrName(id); if (this.element) { this.tagName = this.element.tagName; } else { this.tagName = null; return; } this.tagName = this.element.tagName; this.defaultValue = defaultValue && defaultValue !='undefined'?defaultValue:''; this.overwrite = overwrite && overwrite != 'undefined'?overwrite:false; this.updateAgentItems = false; this.allowFunctionsAndParams = false; this.isDefaultMode = function () {return this.defaultValue.localeCompare(this.getElementValue()) == 0;} this.isEmpty = function () { if(this.getElementValue()) { return this.getElementValue().localeCompare("") == 0; } else { return true; } } this.setDefaultValue = function () {this.setElementValue(this.defaultValue);this.updateStyle(true);} this.removeDefaultValue = function() {if (this.isDefaultMode()) {this.setElementValue("");this.updateStyle(false);} } } ElementProcessor.prototype.setDropLocation = function(event) { //We were checking for default mode in here. //However this caused problems for drop zones where the //the cursor was moving all over the place and where the cursor //is you are able to insert text. //So I changed this to always create the textrange and set the focus. if (cf.browserCheck.isIE5Up()) { // create a textRange - bases on the element var textRange = this.element.createTextRange(); if (this.element.disabled) { return; } this.element.focus(); try { //The div being dragged is sometimes slow moving which //will result in the cursor moving over the div and if //we are over a drop zone with text, where the cursor //is beign shifted from character to character you will //get an error with the pointer location. //Try catch will; resolve this problem for now. (always has been there) // set the position of the textRange if(isIE10()){ textRange.moveToPoint(event.clientX, event.clientY); } else{ textRange.moveToPoint(event.x, event.y); } //textRange.moveToPoint(event.x, event.y); } catch(e) { //do nothing } // text input fields do not position the cursor so move the insertion point to the end. if(this.tagName == "INPUT" ) { textRange.moveEnd("textedit"); textRange.collapse(false); } textRange.select(); } } /** * Drop text is an array of text. */ ElementProcessor.prototype.process = function(dropText) { if (dropText) { if (this.overwrite) { if (dropText.length == 1) { this.setElementValue(""); } else { alert(parent.singleItemAllowed_string); return; } } this.defaultTextProcess(dropText.join("")); parent.getAgentItemsListener().updateField(this.id, this.getElementValue(this.id)); } else { return; } } ElementProcessor.prototype.updateStyle = function(useDefault) { // check to see if we are dropping into an area with default text if (this.tagName.localeCompare("TEXTAREA") == 0) { // check to see if we have got hint text if (this.defaultValue.length > 0 && useDefault) { this.element.className="hintText_active"; } else { this.element.className="hintText_inactive"; } } } ElementProcessor.prototype.getElementValue = function() { var prop = this.getElementProperty(); var value = null; if (prop) { if (this.element) { value = this.element[prop]; } } return value; } ElementProcessor.prototype.setElementValue = function(value) { var isDefault = false; //alert("setting element value"); if (!value && value != "") { isDefault = true; value = this.defaultValue; }else if ("" == value) { isDefault = true; }else{ isDefault = this.defaultValue.localeCompare(value) == 0; } this.updateStyle(isDefault); var prop = this.getElementProperty(); this.element[prop] = value; } ElementProcessor.prototype.updateElementValue = function(value) { if (!value || value == 'undefined') { return; } if (this.isDefaultMode()) { this.removeDefaultValue(); } var prop = this.getElementProperty(); //Give the element we are updating focus. //it is a bit strange that we update value //without giving focus. if (isFocusable(this.element)) { this.element.focus(); } if (this.overwrite) { this.element[prop] = value; } else { this.element[prop] += value; } } ElementProcessor.prototype.getElementProperty = function() { if (this.tagName) { // check to see if we are dropping into an area with default text if (this.tagName.localeCompare("TEXTAREA") == 0) { // need to some more local processing of what we're going to insert return "value"; } else if (this.tagName.localeCompare("INPUT") == 0) { // need to do some more local processing of what we're going to insert return "value"; } else if (this.tagName.localeCompare("TD") == 0) { return "innerHTML"; } else if (this.tagName.localeCompare("BODY") == 0) { return "innerHTML"; } } } ElementProcessor.prototype.defaultTextProcess = function(dropText) { // this is the part that actually inserts the data if (cf.browserCheck.isIE5Up()) { // Get selection & text range from selection. var sel = document.selection; var textRange = sel.createRange(); this.element.focus(); //test if the selection can be used for the drop if(!this.useSelection(this.element,textRange.parentElement())) { textRange = this.element.createTextRange(); textRange.moveEnd("textedit"); textRange.collapse(false); textRange.select(); } textRange.text = dropText; //collapse the range to the right after dropping textRange.collapse(false); } else if (this.element.selectionStart || this.element.selectionStart == '0') { // MOZ // var startPos = this.element.selectionStart; var endPos = this.element.selectionEnd; this.element.focus(); this.element.value = this.element.value.substring(0, startPos) + dropText + this.element.value.substr(endPos); } else { this.element.focus(); this.updateElementValue(dropText); } } /* * Check if the selection exists as a child element inside the drop control. This is needed to be done * because it is possible to select arbitrary areas of non-input HTML on a web page. Also, some drop controls * have HTML inside them such as the email body, which can contain such things as HTML tables. * * this.element The drop control * selElement The current document selection * return true if this selElement is a child of the drop control */ ElementProcessor.prototype.useSelection = function (our_element,selElement) { //set the found bool var found = our_element == selElement; //check for child nodes in the drop control if (our_element.hasChildNodes()) { //get the children var children = our_element.childNodes; //loop through the children for (var i=0;(i