安全getElementById或尝试确定ID是否存在于GUI中 [英] Safe getElementById or try to determine if ID exists in GUI

查看:98
本文介绍了安全getElementById或尝试确定ID是否存在于GUI中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

方法 UiInstance.getElementById(ID)总是返回 GenericWidget 对象,即使ID不存在。

Method UiInstance.getElementById(ID) always returns GenericWidget object, even if ID does not exist.

有没有办法找出返回的对象在我的应用中不存在,或者检查UI是否包含给定ID的对象?

Is there some way how to find out that returned object does not exist in my app, or check whether UI contains object with given ID?

使用GUI构建器创建的UI解决方案:

Solution for UI created with GUI builder:

function getSafeElement(app, txtID) {
    var elem = app.getElementById(txtID);
    var bExists = elem != null && Object.keys(elem).length < 100;
    return bExists ? elem : null;
}

如果ID不存在,则返回null。我没有测试所有窗口小部件的边界长度,所以要小心并使用GUI进行测试。

It returns null if ID does not exist. I didn't test all widgets for keys length boundary, so be careful and test it with your GUI.

编辑:此解决方案仅适用于 doGet()函数。它在服务器处理程序中不起作用,所以在这种情况下,请将它与@ corey-g answer结合使用。

This solution works only within doGet() function. It does not work in server handlers, so in this case use it in combination with @corey-g answer.

推荐答案

只能在您创建窗口小部件的同一执行中工作,而不能在您检索窗口小部件的后续事件处理程序中工作,因为在这种情况下,无论它是否存在,所有东西都是GenericWidget。

This will only work in the same execution that you created the widget in, and not in a subsequent event handler where you retrieve the widget, because in that case everything is a GenericWidget whether or not it exists.

您可以亲自看到解决方案失败:

You can see for yourself that the solution fails:

function doGet() {
  var app = UiApp.createApplication();
  app.add(app.createButton().setId("control").addClickHandler(
      app.createServerHandler("clicked")));
  app.add(app.createLabel(exists(app)));
  return app;
}

function clicked() {
  var app = UiApp.getActiveApplication();
  app.add(app.createLabel(exists(app)));
  return app;
}

function exists(app) {
  var control = app.getElementById("control");
  return control != null && Object.keys(control).length < 100;
}

应用程序首先会打印'true',但在点击处理程序中它会打印'假'为同一个部件。

The app will first print 'true', but on the click handler it will print 'false' for the same widget.

这是设计; GenericWidget是一个在浏览器中排序到widget的指针。我们不会跟踪您创建的小部件,以减少浏览器和脚本之间的数据传输和延迟(否则,我们必须发送关于每个事件处理程序中存在的小部件的长列表)。你应该跟踪你创建的内容,并且只询问你已经知道存在的小部件(并且你已经知道真实类型)。

This is by design; a GenericWidget is a "pointer" of sorts to a widget in the browser. We don't keep track of what widgets you have created, to reduce data transfer and latency between the browser and your script (otherwise we'd have to send up a long list of what widgets exist on every event handler). You are supposed to keep track of what you've created and only "ask" for widgets that you already know exist (and that you already know the "real" type of).

如果您确实想跟踪存在哪些小部件,那么您有两个主要选项。首先是在创建小部件时将条目记录到ScriptDb中,然后再查找它们。例如:

If you really want to keep track of what widgets exist, you have two main options. The first is to log entries into ScriptDb as you create widgets, and then look them up afterwards. Something like this:

function doGet() {
  var app = UiApp.createApplication();
  var db = ScriptDb.getMyDb();
  // You'd need to clear out old entries here... ignoring that for now
  app.add(app.createButton().setId('foo')
      .addClickHandler(app.createServerHandler("clicked")));
  db.save({id: 'foo', type: 'button'});
  app.add(app.createButton().setId('bar'));
  db.save({id: 'bar', type: 'button'});
  return app
}

然后在处理程序中,您可以查看它的内容:

Then in a handler you can look up what's there:

function clicked() {
  var db = ScriptDb.getMyDb();
  var widgets = db.query({}); // all widgets
  var button = db.query({type: 'button'}); // all buttons
  var foo = db.query({id: 'foo'}); // widget with id foo
}

另外,你可以在UiApp中完成使用标签

Alternatively, you can do this purely in UiApp by making use of tags

function doGet() {
  var app = UiApp.createApplication();
  var root = app.createFlowPanel();  // need a root panel
  // tag just needs to exist; value is irrelevant.
  var button1 = app.createButton().setId('button1').setTag(""); 
  var button2 = app.createButton().setId('button2').setTag("");
  // Add root as a callback element to any server handler
  // that needs to know if widgets exist
  button1.addClickHandler(app.createServerHandler("clicked")
      .addCallbackElement(root));
  root.add(button1).add(button2);
  app.add(root);
  return app;
}

function clicked(e) {
  throw "\n" +
      "button1 " + (e.parameter["button1_tag"] === "") + "\n" + 
      "button2 " + (e.parameter["button2_tag"] === "") + "\n" + 
      "button3 " + (e.parameter["button3_tag"] === "");
}

这会抛出:

This will throw:

button1 true
button2 true
button3 false

,因为按钮1和2存在,但3不存在。你可以通过在标签中存储类型来获得更好的效果,但这足以检查小部件的存在。它的工作原理是因为根的所有孩子都被添加为回调元素,并且所有回调元素的标签都与处理程序一起发送。请注意,这听起来非常昂贵,而且具有大量小部件的应用程序可能会影响性能,尽管在许多情况下它可能是可以的,特别是如果您只将根作为回调元素添加到实际需要验证的处理程序任意小部件的存在。

because buttons 1 and 2 exist but 3 doesn't. You can get fancier by storing the type in the tag, but this suffices to check for widget existence. It works because all children of the root get added as callback elements, and the tags for all callback elements are sent up with the handler. Note that this is as expensive as it sounds and for an app with a huge amount of widgets could potentially impact performance, although it's probably ok in many cases especially if you only add the root as a callback element to handlers that actually need to verify the existence of arbitrary widgets.

这篇关于安全getElementById或尝试确定ID是否存在于GUI中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆