How to replace or destroy a tab using the Firefox Add-on SDK? - firefox

I did not find anything in the Firefox Add-on SDK (Tab API) that can destroy a tab or replace it with a new tab. I can find the Tab ID, Tab URL, or other identifier. Is there any way to replace or destroy a tab?

Use tab.close(callback).
What do you mean by replace? If you just want to change the URL, then use tab.url = url.

I don't know about SDK, but you can destroy and replace one tab with another tab.
This is how to do it with non-sdk:
How to close a tab by its "id"
var tabIdToClose = 'panel-3-1';
Cu.import('resource://gre/modules/Services.jsm');
var DOMWindows = Services.wm.getEnumerator('navigator:browser');
while (DOMWindows.hasMoreElements()) {
var aDOMWindow = DOMWindows.getNext();
if (aDOMWindow.gBrowser && aDOMWindow.gBrowser.tabContainer) {
var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
for (var i = 0; i < tabs.length; i++) {
var aTab = tabs[i];
var aTabId = aTab.getAttribute('linkedpanel');
console.log('tab id:', aTabId);
if (aTabId == tabIdToClose) {
aDOMWindow.gBrowser.removeTab(aTab);
}
}
} else {
//this window does not have any tabs
}
}
This is how to replace tab with another tab and close the first tab.
var tabIdToReplace = 'panel-3-248';
var tabIdToReplaceWith = 'panel-3-246'; //this tab will be closed, but its contents will be in tabIdToReplace
var aTabToReplace;
var aTabToReplaceWith;
Cu.import('resource://gre/modules/Services.jsm');
var DOMWindows = Services.wm.getEnumerator('navigator:browser');
while (DOMWindows.hasMoreElements()) {
var aDOMWindow = DOMWindows.getNext();
if (aDOMWindow.gBrowser && aDOMWindow.gBrowser.tabContainer) {
var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
for (var i = 0; i < tabs.length; i++) {
var aTab = tabs[i];
var aTabId = aTab.getAttribute('linkedpanel');
console.log('tab id:', aTabId);
if (aTabId == tabIdToReplace) {
aTabToReplace = aTab;
} else if (aTabId == tabIdToReplaceWith) {
aTabToReplaceWith = aTab;
}
if (aTabToReplace && aTabToReplaceWith) {
aTabToReplaceWith.ownerDocument.defaultView.gBrowser.swapBrowsersAndCloseOther(aTabToReplace, aTabToReplaceWith);
break;
}
}
} else {
//this window does not have any tabs
}
}
If you just want to swap the tabs without closing either then do this
I havent completed this so the swap isn't perfect, like I have to set the iconURL and title of the tab that would have been closed: https://gist.github.com/Noitidart/9b335a460f53b0390336

Related

How to show duplicates in a UI when searched in google sheets?

I am developing a tracking system for candidates
Attached a search button.
But I want a UI to pop up which will show the duplicates if present.
And when one of the duplicates is clicked, it will fill the required details in the form
I have made this.
But the results are the first row which matches the search text in B4
function Search()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("Form");
var dataS = ss.getSheetByName("Data");
var str = formS.getRange("B4").getValue();
var values = dataS.getDataRange().getValues();
var valuesFound = false;
for (var i = 0; i < values.length; i++)
{
var rowValue = values[i];
if (rowValue[0] == str) {
formS.getRange("B7").setValue(rowValue[0]) ;
formS.getRange("B9").setValue(rowValue[1]) ;
formS.getRange("B11").setValue(rowValue[2]) ;
formS.getRange("B13").setValue(rowValue[3]) ;
formS.getRange("E7").setValue(rowValue[4]) ;
formS.getRange("E9").setValue(rowValue[5]) ;
formS.getRange("E11").setValue(rowValue[6]) ;
formS.getRange("E13").setValue(rowValue[7]) ;
return;
}
}
if(valuesFound==false){
var ui = SpreadsheetApp.getUi();
ui.alert("No record found!");
}
}
Description
You could get all the first name matches and show them in a dialog, numbered so its easier to pick. Once the user picks the name you can fill out the form.
To use a dropdown and pick a name, that would require a custom dialog. Doable but more complex.
This script is executed from a menu item.
Data
Script
function search() {
try {
let spread = SpreadsheetApp.getActiveSpreadsheet();
let dataS = spread.getSheetByName("Data");
let str = "John";
let values = dataS.getDataRange().getValues();
let rowValue = values.filter( row => row[0] === str );
let ui = SpreadsheetApp.getUi();
let prompt = "";
rowValue.forEach( (row,i) => prompt = prompt.concat((i+1).toString(),": ",row[0], " ",row[1],"\n"));
if( rowValue.length === 0 ) {
ui.alert("Name not found ["+str+"]");
return;
}
else if( rowValue.length > 1 ) {
let response = ui.prompt("Pick a name",prompt,ui.ButtonSet.OK_CANCEL);
if( response.getSelectedButton() == ui.Button.OK ) {
str = response.getResponseText();
str = parseInt(str)-1;
rowValue = rowValue[str];
}
}
else {
rowValue = rowValue[0];
}
ui.alert(rowValue.toString());
// Now you can fill out your form with rowValue
}
catch(err) {
SpreadsheetApp.getUi().alert(err);
}
}
Reference
Array.filter()
Array.forEach()
SpreadsheetApp Ui prompt
Description
So I decided to show how a custom dialog can be used to display a list of names to pick from. First a Ui dialog is displayed to use a filter name. If no name is specified all names will be listed.
Using HTMLService a custom dialog is build using the the pushed variable option for an HTM Template.
Once a name is picked from the list google.script.run is used to return the name to the server and the form can be built from there.
Code.gs
function onOpen(e) {
var menu = SpreadsheetApp.getUi().createMenu("My Menu");
menu.addItem("Test","showTest");
menu.addToUi();
}
function showTest() {
try {
let ui = SpreadsheetApp.getUi();
let response = ui.prompt("What name do you want to search for",ui.ButtonSet.OK_CANCEL);
if( response.getSelectedButton() == ui.Button.OK ) {
var name = response.getResponseText();
if( name === "" ) name = "__All";
}
let spread = SpreadsheetApp.getActiveSpreadsheet();
let dataS = spread.getSheetByName("Data");
let data = dataS.getRange(1,1,dataS.getLastRow(),2).getValues(); // Get range A1:B
if( name !== "__All" ) {
data = data.filter( row => row[0] === name );
}
if( data.length === 0 ) {
ui.alert("No names mathcing ["+name+"] found");
return;
}
let html = HtmlService.createTemplateFromFile('HTML_Test');
html.data = data;
html = html.evaluate();
SpreadsheetApp.getUi().showModalDialog(html,"Show Test");
}
catch(err) {
SpreadsheetApp.getUi().alert(err);
}
}
function pickName(name) {
try {
let spread = SpreadsheetApp.getActiveSpreadsheet();
let dataS = spread.getSheetByName("Data");
dataS.getRange(1,5).setValue(name);
// Build your form here
}
catch(err) {
console.log(err);
}
}
HTML_Test.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<select id="selectName">
<? for (let i = 0; i < data.length; i++) { ?>
<option><?= data[i][0]+" "+data[i][1] ?></option>
<? } ?>
</select>
<input type="button" onclick="buttonOnClick()" value="Submit">
<script>
function buttonOnClick() {
let name = document.getElementById("selectName").value;
google.script.run.pickName(name);
google.script.host.close();
}
</script>
</body>
</html>
Reference
HTMLService
HTML Template
google.script.run
google.script.host

Why I can't change style in mxEvent.CHANGE event first time?

I just want to change some style when the CHANGE event fired.But when I change the model by insert or move a vertex or edge, the style didn't change. And the changed vertex will change it's style after I change anything again. Is anybody konws why?
Here is my code:
graph.getModel().addListener(mxEvent.CHANGE, function(sender, evt){
if(graphInited){
graph.getModel().beginUpdate();
try {
var changes = evt.getProperty('edit').changes;
for (var i = 0; i < changes.length; i++) {
var change = changes[i];
var state = graph.view.getState(change.cell);
if(state!=null){//color #1C86EE means new insert
if(state.style[mxConstants.STYLE_IMAGE_BACKGROUND]!="#1C86EE"
&& state.style[mxConstants.STYLE_STROKECOLOR]!="#1C86EE"
&& state.style[mxConstants.STYLE_FONTCOLOR]!="#1C86EE"){
graph.setCellStyles(mxConstants.STYLE_IMAGE_BACKGROUND, '#68228B', [change.cell]);
graph.setCellStyles(mxConstants.STYLE_STROKECOLOR, '#68228B', [change.cell]);
}
}
}
} finally {
graph.getModel().endUpdate();
}
}
});
I made more recon and fond simpler solution than in my first answer.
You need to add:
evt.consume()
graph.refresh()
So final code would looks like:
graph.getModel().addListener(mxEvent.CHANGE, function(sender, evt){
if(graphInited){
graph.getModel().beginUpdate();
evt.consume();
try {
var changes = evt.getProperty('edit').changes;
for (var i = 0; i < changes.length; i++) {
var change = changes[i];
var state = graph.view.getState(change.cell);
if(state!=null){//color #1C86EE means new insert
if(state.style[mxConstants.STYLE_IMAGE_BACKGROUND]!="#1C86EE"
&& state.style[mxConstants.STYLE_STROKECOLOR]!="#1C86EE"
&& state.style[mxConstants.STYLE_FONTCOLOR]!="#1C86EE"){
graph.setCellStyles(mxConstants.STYLE_IMAGE_BACKGROUND, '#68228B', [change.cell]);
graph.setCellStyles(mxConstants.STYLE_STROKECOLOR, '#68228B', [change.cell]);
}
}
}
} finally {
graph.getModel().endUpdate();
graph.refresh();
}
}
});

gridpanel ext.net communication failure error firefox

I have a ext:gridpanel in my application and we have given the user the ability to arrange columns as per his convenience in the grid.
We also have given a button reset columns to default so that user can go back to the original gridpanel column order.
A method is written in javascript file to bring back the grid to original state when the user clicks "Reset Column to Default button"
The click handler for this button calls the method-"gridpanel_restore"
The code for this method is:-
var gridpanel_restore = function (grid) {
try
{
grid._State = appGlobal.getGridState(grid);
if (grid._State == grid._DefaultState) {
return;
}
grid._State = grid._DefaultState;
var settings = Ext.decode(grid._State);
var cm = grid.getColumnModel();
if (cm.isLocked != null) {
for (var i = cm.columns.length - 1; i > 0; i--) {
if (cm.isLocked(i) && !settings.settings[0].lockField.contains(i)) {
cm.setLocked(i, false, false);
}
}
for (var j = 0; j < settings.settings[0].lockField.length; j++) {
if (!cm.isLocked(i)) cm.setLocked(settings.settings[0].lockField[j], true, false);
}
}
if (settings.settings[0].state.sort) {
}
else {
grid.store.sortInfo = null;
}
grid.applyState(settings.settings[0].state);
var lastColumn = cm.getColumnAt(cm.columns.length - 1);
cm.setColumnWidth(cm.columns.length - 1, lastColumn.width - 1, false);
noMask = true;
CMS.ResetUserSettings(grid._ControlID);
if (settings.settings[0].state.group != null) {
async: false
window.location.href = window.location.href;
}
}
catch (err) {
}
}
This code works perfectly fine in IE but in firefox I get Communication failure on line "window.location.href = window.location.href;" on line 34
I have used this line because the page should be reloaded after setting columns to default otherwsise the grid does not render properly.
I have seen posts related to this but could not find a solution.
Please help. I have already asked this question in ext.net forum but no answer.

Form Validation Before Submission

I can't get my form to validate before it is submitted to my spreadsheet. Once I click submit it does nothing...
I also am not sure how to validate the Date to make sure it is in the correct format before submission. I have tried to setup the validation but before I can test it, i have to be able to submit and get validation results.
What am I doing wrong? I have included the code below:
function doGet() {
var app = UiApp.createApplication().setTitle('DHS: Kurzweil Calendar');
//Create a panel which holds all the form elelemnts
var vrtMainPanel = app.createVerticalPanel().setId('vrtMainPanel');
//Create Spreadsheet Source
var spSheet = SpreadsheetApp.openById('0Aur3owCpuUY-dFF0dVZXb3I1Yjlpbzg3SXFIaklEcUE');
var spTeacherList = spSheet.getSheetByName('TeacherList');
var spSubjectList = spSheet.getSheetByName('SubjectList');
var spPeriodList = spSheet.getSheetByName('PeriodList');
var spCountList = spSheet.getSheetByName('CountList');
//Create the form elements
var hdlTeacherName = app.createServerHandler('getTeacherName').addCallbackElement(vrtMainPanel);
var lbxTeacherName = app.createListBox().setId('lbxTeacherName').setName('lbxTeacherName').addChangeHandler(hdlTeacherName);
var lstTeacherNames = spTeacherList.getRange(1,1,spTeacherList.getLastRow(),1).getValues();
lstTeacherNames.sort();
for (var l = 0; l < lstTeacherNames.length; l++) {
lbxTeacherName.addItem(lstTeacherNames[l],l);
}
var lblTeacherName = app.createLabel('Teacher Name:');
var txtTeacherName = app.createTextBox().setName('txtTeacherName').setId('txtTeacherName').setVisible(false);
var lblExt = app.createLabel('Ext:');
var txtExt = app.createTextBox().setName('txtExt').setId('txtExt');
//Set DateBox to Tomorrow's Date
var tomorrow =new Date(new Date(new Date().setHours(0,0,0,0)).setDate(new Date().getDate() + 1));// set hours, min, sec & milliSec to 0 and day=day+1
//Logger.log(tomorrow);
var lblDate = app.createLabel('Date of Test:');
var boxDate = app.createDateBox().setId('boxDate').setName('boxDate').setFormat(UiApp.DateTimeFormat.DATE_SHORT).setValue(tomorrow);
var lbxSubject = app.createListBox().setId('lbxSubject').setName('lbxSubject');
var lstSubjects = spSubjectList.getRange(1,1,spSubjectList.getLastRow(),1).getValues();
lstSubjects.sort();
for (var l = 0; l < lstSubjects.length; l++) {
lbxSubject.addItem(lstSubjects[l]);
}
var lbxPeriod = app.createListBox().setId('lbxPeriod').setName('lbxPeriod');
var lstPeriods = spPeriodList.getRange(1,1,spPeriodList.getLastRow(),1).getValues();
lstPeriods.sort();
for (var l = 0; l < lstPeriods.length; l++) {
lbxPeriod.addItem(lstPeriods[l]);
}
var lblStudentNum = app.createLabel('Number of Students:');
var lbxStudentNum = app.createListBox().setId('lbxStudentNum').setName('lbxStudentNum');
var lstStudentNums = spCountList.getRange(1,1,spCountList.getLastRow(),1).getValues();
lstStudentNums.sort();
for (var l = 0; l < lstStudentNums.length; l++) {
lbxStudentNum.addItem(lstStudentNums[l]);
}
var txtSourceGrp = app.createTextBox().setName('txtSourceGrp').setVisible(false);
var txtTypeGrp = app.createTextBox().setName('txtTypeGrp').setVisible(false);
var txtElementsID = app.createTextBox().setName('txtElementsID').setText('Elements Test ID').setVisible(false);
var txtQuiaLink = app.createTextBox().setName('txtQuiaLink').setText('Quia Test Link').setVisible(false);
var txtQuiaPass = app.createTextBox().setName('txtQuiaPass').setText('Quia Test Passphrase').setVisible(false);
//Create Source Radio Button Group
var radHCopy = app.createRadioButton('group1', 'Hard-Copy').setFormValue('Hard-Copy').addClickHandler(app.createClientHandler().forTargets(txtSourceGrp).setText('Hard-Copy'));
var radECopy = app.createRadioButton('group1', 'Electronic-Copy').setFormValue('Electronic-Copy').addClickHandler(app.createClientHandler().forTargets(txtSourceGrp).setText('Electronic-Copy'));
//Create Type Radio Button Group
var radTExam = app.createRadioButton('group2', 'Teacher-Made Exam').setFormValue('Teacher-Made Exam').addClickHandler(app.createClientHandler().forTargets(txtTypeGrp).setText('Teacher-Made Exam'));
var radEExam = app.createRadioButton('group2', 'Elements Exam').setFormValue('Elements Exam').addClickHandler(app.createClientHandler().forTargets(txtTypeGrp).setText('Elements Exam'));
var radQExam = app.createRadioButton('group2', 'Quia Exam').setFormValue('Quia Exam').addClickHandler(app.createClientHandler().forTargets(txtTypeGrp).setText('Quia Exam'));
var btnValidate = app.createButton('Create Event');
//Client Handlers for textBoxes
var showTxtElementHandler = app.createClientHandler().forTargets(txtElementsID).setVisible(true);
var hideTxtElementHandler = app.createClientHandler().forTargets(txtElementsID).setVisible(false);
radEExam.addClickHandler(showTxtElementHandler);
radTExam.addClickHandler(hideTxtElementHandler);
radQExam.addClickHandler(hideTxtElementHandler);
var showTxtQuiaLinkHandler = app.createClientHandler().forTargets(txtQuiaLink).setVisible(true);
var hideTxtQuiaLinkHandler = app.createClientHandler().forTargets(txtQuiaLink).setVisible(false);
radQExam.addClickHandler(showTxtQuiaLinkHandler);
radTExam.addClickHandler(hideTxtQuiaLinkHandler);
radEExam.addClickHandler(hideTxtQuiaLinkHandler);
var showTxtQuiaPassHandler = app.createClientHandler().forTargets(txtQuiaPass).setVisible(true);
var hideTxtQuiaPassHandler = app.createClientHandler().forTargets(txtQuiaPass).setVisible(false);
radQExam.addClickHandler(showTxtQuiaPassHandler);
radTExam.addClickHandler(hideTxtQuiaPassHandler);
radEExam.addClickHandler(hideTxtQuiaPassHandler);
//Create validation handler
var valSubmit = app.createServerClickHandler('valSubmit');
valSubmit.addCallbackElement(vrtMainPanel);
//Add this handler to the button
btnValidate.addClickHandler(valSubmit);
//Add all the elemnts to the panel
var formGrid = app.createGrid(12,3).setCellPadding(3);
vrtMainPanel.add(formGrid);
formGrid
.setWidget(0,0,lbxTeacherName)
.setWidget(0,1,txtExt)
.setWidget(0,2,txtTeacherName)
.setWidget(1,0,lbxPeriod)
.setWidget(1,1,lbxSubject)
.setWidget(2,0,lblDate)
.setWidget(2,1,boxDate)
.setWidget(3,0,lblStudentNum)
.setWidget(3,1,lbxStudentNum)
.setWidget(4,0,radHCopy)
.setWidget(4,1,radECopy)
.setWidget(5,0,radTExam)
.setWidget(6,0,radEExam)
.setWidget(6,1,txtElementsID)
.setWidget(7,0,radQExam)
.setWidget(7,1,txtQuiaLink)
.setWidget(8,1,txtQuiaPass)
.setWidget(9,0,txtSourceGrp)
.setWidget(9,1,txtTypeGrp)
.setWidget(10,0,btnValidate)
//Add this panel to the application
app.add(vrtMainPanel);
//Return the application
return app;
}
function valSubmit(e) {
var flag = 0;
var app = UiApp.getActiveApplication();
var Teacher = e.parameter.txtTeacherName;
var Ext = e.parameter.txtExt;
var Subject = e.parameter.lbxSubject;
var Period = e.parameter.lbxPeriod;
var Date = e.parameter.boxDate;
var StudentNum = e.parameter.lbxStudentNum;
var Source = e.parameter.txtSourceGrp;
var Type = e.parameter.txtTypeGrp;
var ElementsID = e.parameter.txtElementsID;
var QuiaLink = e.parameter.txtQuiaLink;
var QuiaPass = e.parameter.txtQuiaPass;
if (Teacher == '' || Teacher == '-- Select Teacher --') {
app.getElementById('vldTeacherName').setText('* Select Teacher').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Ext == '') {
app.getElementById('vldExt').setText('* Select Teacher Again').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Subject == '' || Subject == '-- Select Subject --') {
app.getElementById('vldSubject').setText('* Select Subject').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Period == '' || Period == '-- Select Period --') {
app.getElementById('vldPeriod').setText('* Select Period').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Date == '' || Date == Utilities.formatDate(Date, 'EST', 'yyyy-mm-dd')) {
app.getElementById('vldDate').setText('* Date must be entered as yyyy-mm-dd').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (StudentNum == '' || StudentNum == '-- Select # --') {
app.getElementById('vldStudentNum').setText('* Select Student #').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Source == '' || Source == false) {
app.getElementById('vldSourceGrp').setText('* Select either Hard Copy or Electronic Copy').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Type == '' || Type == false) {
app.getElementById('vldTypeGrp').setText('* Select either Teacher-Made Exam, Elements Exam, or Quia Exam').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (ElementsID == '' && Type == 'Elements Exam') {
app.getElementById('vldElementsID').setText('* Enter Elements ID').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (QuiaLink == '' || QuiaPass == '' && Type == 'Quia Exam') {
app.getElementById('vldQuia').setText('* Enter Quia Link and/or Passphrase').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (flag == 0) {
app.getElementById('lblSuccess').setStyleAttribute("color", "#F00").setVisible(true);
//Create handler which will execute 'createEvents(e)' on clicking the button
var evtHandler = app.createServerClickHandler('createEvents');
var vrtMainPanel = app.getElementById(vrtMainPanel);
evtHandler.addCallbackElement(vrtMainPanel);
}
}
function valHandler(e) {
var app = UiApp.createApplication().setTitle('DHS: Kurzweil Calendar');
//Create a panel which holds all the form elelemnts
var vrtMainPanel = app.createVerticalPanel().setId('vrtMainPanel');
var lblSuccess = app.createLabel('Check your information below, if everything looks correct you may confirm your event...').setName('lblSuccess').setId('lblSuccess').setVisible(false);
var lblNoSuccess = app.createLabel('There were issues with the creation of your event... click BACK, and make the following corrections:').setName('lblNoSuccess').setId('lblNoSuccess').setVisible(false);
var vldTeacherName = app.createLabel().setId('vldTeacherName').setVisible(false);
var vldExt = app.createLabel().setId('vldExt').setVisible(false);
var vldDate = app.createLabel().setId('vldDate').setVisible(false);
var vldSubject = app.createLabel().setId('vldSubject').setVisible(false);
var vldPeriod = app.createLabel().setId('vldPeriod').setVisible(false);
var vldStudentNum = app.createLabel().setId('vldStudentNum').setVisible(false);
var vldSourceGrp = app.createLabel().setId('vldSourceGrp').setVisible(false);
var vldTypeGrp = app.createLabel().setId('vldTypeGrp').setVisible(false);
var vldElementsID = app.createLabel().setId('vldElementsID').setVisible(false);
var vldQuia = app.createLabel().setId('vldQuia').setVisible(false);
var btnCreate = app.createButton('Corfirm Event');
//Add this handler to the button
var evtHandler = app.getElementById('evtHandler');
btnCreate.addClickHandler(evtHandler);
//Add all the elemnts to the panel
var formGrid = app.createGrid(13,3).setCellPadding(3);
vrtMainPanel.add(formGrid);
formGrid
.setWidget(0,0,lblSuccess)
.setWidget(1,0,lblNoSuccess)
.setWidget(2,0,vldTeacherName)
.setWidget(3,0,vldExt)
.setWidget(4,0,vldDate)
.setWidget(5,0,vldSubject)
.setWidget(6,0,vldPeriod)
.setWidget(7,0,vldStudentNum)
.setWidget(8,0,vldSourceGrp)
.setWidget(9,0,vldTypeGrp)
.setWidget(10,0,vldElementsID)
.setWidget(11,0,vldQuia)
.setWidget(12,0,btnCreate)
//Add this panel to the application
app.add(vrtMainPanel);
//Return the application
return app;
}
I've been spending a lot of time on form validation and I ended up with 2 possible solutions that work pretty well but since I can't decide which one is the best I use sometimes the first... and sometimes the second...
I'll show the idea of both solution, make your choice.
The 'logical' one : use client validation to enable the submit button and a few other client handler validations to show/hide warning labels near the fields that have to be filled. It works great but I must admit it can be tricky to write the script for it and needs quite a lot of code. (see examples in these post among others : Form validation on fields and FileUpload
Form validation using client handler : why does input sequence order change the result?
Use a server handler like you did in your code but replace the "createEvent" button with an intermediate button that instead of sending you directly to the event creation function calls a "fake" function that shows a summary of the requested data in a HTML widget with a nice looking presentation and another button that one use to confirm the event creation (and actually create the event) making a sort of 2 steps confirmation that is definitely user friendly. (and includes a way to go back one step to change/append the submitted data.
Both solution as I already said have pro and cons, the second one is just probably easier to write a script for it.
feel free to comment and/or ask for further details if the references I mentioned are not clear enough.
EDIT : here is an example of the 2cond approach and the spreadsheet with the included script (read only, make a copy to view/edit script and change the spreadsheet ID in the script if you want to run your own version))
The instructions are in french but it shouldn't be too hard to translate ... sorry about that :-) The SS has a marter sheet where you can define the question in the form and the script generates a custom form. There are tools to count responses, print log sheet per day and send confirmation emails.

NicEdit link creation doesn't work in IE 8 and FireFox if text wasn't selected

I have a problem with nicEdit link creation tool in IE and Firefox.
In general, I think the problem is related to the execCommand in IE and FireFox. It seems document doesn't get updated after execCommand executes.
This is an example of my problem with nicEdit create link command.
if(!this.ln) {
var tmp = 'javascript:nicTemp();';
this.ne.nicCommand("createlink",tmp);
this.ln = this.findElm('A','href',tmp);
// set the link text to the title or the url if there is no text selected
alert(this.ln);
if (this.ln.innerHTML == tmp) {
this.ln.innerHTML = this.inputs['title'].value || url;
};
}
The code above is called when no text is selected, Chrome returns 'javascript:nicTemp()' for the alert(this.ln), while IE 8 and Firefox return 'undefined', so the next line after the alert encounters an error in IE and Firefox.
it seems findElem can't find the newly created link by nicCommand which in turn calls execCommand
I had similar problems when I try to find and modify tags created with execCommand, it seems the dom isn't updated to include them.
Am I right? How can I solve this problem? how can I force the document to be updated ....
please help
my trick for nicEdit, in the situation when no text is selected, is to paste the title given via the Add Link form into the document and select it, then the rest code works as it works when a text is selected.
I used the function pasteHtmlAtCaret described in the following link to paste the title
Insert html at caret in a contenteditable div
this.removePane();
var url = this.inputs.href.value;
var selected = getSelected();
var B= 'javascript:nicTemp()';
if (selected == '')
{
var B = url;
pasteHtmlAtCaret(this.inputs['title'].value || url,true);
}
if(!this.ln){
this.inputs.title.value;this.ne.nicCommand("createlink",B);
this.ln=this.findElm("A","href",B)
}
the getSelected is also a simple function as below
function getSelected()
{
if (document.selection)
return document.selection.createRange().text;
else
return window.getSelection();
}
Ahmad, just use this variation of the "submit" function to avoid the "insert/edit" problem with the link, it worked for me:
submit : function(e) {
var url = this.inputs['href'].value;
if(url == "http://" || url == "") {
alert("Introduce una URL valida para crear el Link.");
return false;
}
this.removePane();
if(!this.ln) {
//**************** YOUR CHANGE WITH A BIT OF VARIATION **************
var selected = this.getSelected();
var tmp = 'javascript:void(0)';
if (selected == '') {
tmp = url;
this.pasteHtmlAtCaret(this.inputs['title'].value || tmp, true);
}
//**************** END OF YOUR CHANGE WITH A BIT OF VARIATION **************
this.ne.nicCommand("createlink",tmp);
this.ln = this.findElm('A','href',tmp);
// set the link text to the title or the url if there is no text selected
if (this.ln.innerHTML == tmp) {
this.ln.innerHTML = this.inputs['title'].value || url;
};
}
if(this.ln) {
var oldTitle = this.ln.title;
this.ln.setAttributes({
href: this.inputs['href'].value,
title: this.inputs['title'].value,
target: '_blank'
});
// set the link text to the title or the url if the old text was the old title
if (this.ln.innerHTML == oldTitle) {
this.ln.innerHTML = this.inputs['title'].value || this.inputs['href'].value;
};
}
}
this.removePane();
var url = this.inputs['href'].value;
var selected = getSelected();
var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
var tmp = "";
if(isChrome == true){
tmp=url;
}
else{tmp='javascript:nicTemp()'}
if (selected == '' && isChrome == false)
{
pasteHtmlAtCaret(this.inputs['title'].value || url,true);
}
if (!this.ln) {
//var tmp = this.inputs['title'].value == "" ? this.inputs['href'].value : this.inputs['title'].value;
this.ne.nicCommand("createlink", tmp);
this.ln = this.findElm('A', 'href', tmp);
}
function getSelected()
{
if (document.selection)
return document.selection.createRange().text;
else
return window.getSelection();
}
function pasteHtmlAtCaret(html) {
var sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
//create a link format
el.innerHTML = ''+ html +'';
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}

Resources