自定义小部件中的自定义小部件

问题描述:

无可否认,我仍然是Dojo的新手,而且我一直在使用Javascript,所以在这里找借口和草率的代码或语言。自定义小部件中的自定义小部件

我正在使用Dojo 1.7.1和Spring Roo 1.2.1RELEASE。我通过CDM从Google加载Dojo。

我前段时间创建了一个自定义图像缩略图查看器,可以在我的网站上使用,我可以在Spring Roo的load-scripts.tagx中添加一个模块到我的djConfig中,该模块会在每次页面加载时运行。缩略图Widget不遵循AMD模式,因为当时我无法让它正常工作。

这里是djConfig:

<script type="text/javascript"> 
    var djConfig = { 
      parseOnLoad: false, 
      isDebug: false, 
      locale: '${fn:toLowerCase(userLocale)}', 
      modulePaths: { 
       "message": "${message_dojo_url}", 
       "img.ArtThumbnailWidget": "${artThumbnailWidget_dojo_url}", 
       "img.ArtTableWidget": "${artTableWidget_dojo_url}", 
      }, 
     }; 
    </script> 

这里是JS的thumbailer:

// img.ArtThumbnailWidget 
dojo.provide("img.ArtThumbnailWidget"); 

dojo.require("dojo._base.declare"); 
dojo.require("dojo.parser"); 
dojo.require("dojo.ready"); 
dojo.require("dijit._WidgetBase"); 
dojo.require("dijit._TemplatedMixin"); 
dojo.require("dojox.image.LightboxNano"); 

// Create the widget 
require([ 
     "dojo/_base/declare", 
     "dojo/parser", 
     "dojo/ready", 
     "dijit/_WidgetBase", 
     "dijit/_TemplatedMixin", 
     "dojo/dom", 
     "dojo/dom-construct", 
     "dojo/on", 
     "dojo/text!img/ArtThumbnailWidget/templates/ArtThumbnailWidget.html", 
     "dojox/image/LightboxNano", 
     "dojo/domReady!" 
    ], function(declare, parser, ready, _WidgetBase, _TemplatedMixin, dom, domConstruct, on, template) { 

    dojo.declare("img.ArtThumbnailWidget",[dijit._WidgetBase, dijit._TemplatedMixin], { 
     /* Our properties will go here */ 

     // Art JSON object, default is null 
     art: null, 

     // Viewer ID (the username of the person looking at this image), which will default to null 
     viewerId: null, 

     // maxThumbnailSize is how large of an image to return for the thumbnail. The back-end will resize the thumbnail accordingly 
     maxThumbnailSize: 100, 

     // maxImageSize is how large of an image to return for the LightboxNano. The back-end will resize the image accordingly 
     maxImageSize: 500, 

     // Our template - important! 
     templateString: template, 

     // A class to be applied to the root node in our template 
     baseClass: "artThumbnailWidget", 

     // Specifies there are widgets in the template itself that need to be rendered as well 
     widgetsInTemplate: true, 

     // Competition-related vars 
     competitionUrlBase: null, 
     competitionButtonIconUrl: null, 

     /* This is called once the DOM structure is ready, but before anything is shown */ 
     postCreate: function() { 
      // Get a DOM node reference for the root of our widget 
      var domNode = this.domNode; 

      // Run any parent postCreate processes - can be done at any point 
      this.inherited(arguments); 

      if(this.art!=null && this.viewerId!=null && this.art.owner.name == this.viewerId) {  // If the view is the owner, add the toolbar 
       // TODO: We need to clean this up, make it "prettier", and make the URLs more generic 
       var toolbarNode = domConstruct.create("div", {}, this.containerNode); 

       if(this.competitionUrlBase!=null) { 
        var url = this.competitionUrlBase; 
        if(url.indexOf('?')<0) { // URL does not have a '?' 
         url = url+"?"; 
        } else { // URL has a '?', so we need to tack on and additional '&' 
         url = url+"&"; 
        } 
        url = url+"username="+this.art.owner.name+"&artPieceId="+this.art.id; 

        var compButtonNode = domConstruct.create("a", 
          { 
           href: url, 
          },toolbarNode); 
        var compButtonImg = domConstruct.create("img", 
          { 
           src: this.competitionButtonIconUrl, 
           width: this.maxThumbnailSize/4, 
           height: this.maxThumbnailSize/4, 
          },compButtonNode); 
       } 
      } 
     }, 

     /* This private method is used to re-set the node values when something changes */ 
     _resetNodeValues: function() { 
      if(this.art !=null) { 
       // Using our thumbnailNode attach point, set its src value 
       this.thumbnailNode.src = this.art.url+"?maxSize="+this.maxThumbnailSize; 
       this.thumbnailNode.alt = this.art.title; 
       this.thumbnailNode.width = this.maxThumbnailSize; 
       this.thumbnailNode.height = this.maxThumbnailSize; 

       // Now setup the link for the LightboxNano 
       var lightboxNano = new dojox.image.LightboxNano({ 
        href: this.art.url+"?maxSize="+this.maxImageSize, 
       },this.thumbnailNode); 
      } 
     }, 

     /* This is called anytime the "art" attribute is set. Consider is a "setter" method */ 
     _setArtAttr: function(av) { 
      if (av != null) { 
       // Save it on our widget instance - note that 
       // we're using _set, to support anyone using 
       // our widget's Watch functionality, to watch values change 
       this._set("art", av); 

       this._resetNodeValues(); 
      } else { 
       // We could have a default here...would be an error, since we 
       // shouldn't be calling this without an art object 
      } 
     }, 

     _setMaxThumbnailSizeAttr: function(ms) { 
      // Save it on our widget instance - note that 
      // we're using _set, to support anyone using 
      // our widget's Watch functionality, to watch values change 
      this._set("maxThumbnailSize", ms); 

      this._resetNodeValues(); 
     }, 

     _setMaxImageSizeAttr: function(ms) { 
      // Save it on our widget instance - note that 
      // we're using _set, to support anyone using 
      // our widget's Watch functionality, to watch values change 
      this._set("maxImageSize",ms); 

      this._resetNodeValues(); 
     } 
    });  // End of the widget 

}); 

现在我想添加其他自定义组件,上述缩略图的表。新的代码需要引用这个旧的Widget,但我似乎无法得到它的工作。

新表窗口小部件(到目前为止):

// in "img/ArtTableWidget" 
define([ 
     "dojo/_base/declare", "dojo/parser", 
     "dijit/_WidgetBase", "dijit/_TemplatedMixin", 
     "dojo/dom", "dojo/dom-construct","img/ArtThumbnailWidget", 
     "dojo/text!./ArtTableWidget/templates/ArtTableWidget.html"], 
    function(declare,parser,_WidgetBase,_TemplatedMixin, dom, domConstruct, ArtThumbnailWidget, template) { 
     return declare("img.ArtTableWidget",[dijit._WidgetBase,dijit._TemplatedMixin], { 
      // Default values for the ArtTable 

      // The base URL to use for downloading the photos 
      artUrlBase: null, 

      // The base URL used for submitting competitions and the button URL 
      newCompetitionUrlBase: null, 
      newCompetitionButtonIconUrl: null, 

      // Indicates what params on the URL are used to control page 
      // and size. These will be appended to the URL as needed. 
      pageNumberParameterName: "page", 
      pageSizeNumberParameterName: "size", 

      // Holds the page and size 
      page: 1, 
      size: 15, 
      totalPages: 0, 

      columns: 3, 

      // Holds the current list of "art" 
      artList: [], 

      // The userid currently viewing 
      viewerId: null, 

      // Our HTML template 
      templateString: template, 

      baseClass: "artTableWidget", 

      // Specifies there are widgets in the template itself that need to be rendered as well 
      widgetsInTemplate: true, 

      // Functions // 

      postCreate: function() { 
       this._load(this.page); 
      }, 

      // Loads the given page 
      _load: function(pageToLoad) { 
       if(pageToLoad==null) { 
        pageToLoad=1; 
       } 

       // Generate the URL 
       genUrl = this.artUrlBase.indexOf("?")>=0 ? this.artUrlBase+"&page="+pageToLoad+"&size="+this.size : this.artUrlBase+"?page="+pageToLoad+"&size="+this.size; 

       // Make the call to the backend 
       dojo.xhrGet({ 
        url: genUrl, 
        handleAs: "json", 
        tableWidget: this, 
        load: function(data,ioArgs) { 
         this.tableWidget.page = data.page; 
         this.tableWidget.totalPages = data.totalPages; 
         this.tableWidget.artList = data.data; 

         this.tableWidget._updateTable(); 
        } 
       }); 
      }, 

      _updateTable: function() { 
       // Fix the buttons at the bottom 

       // Clear the artTable 
       domConstruct.empty(this.artTable); 

       // Loop through the art and build the rows 
       tableRow = tableRow = domConstruct.create("tr",{},this.artTable); 
       dojo.forEach(this.artList,function(art,index) { 
        if(index % columns == 0) { 
         tableRow = domConstruct.create("tr",{},this.artTable); 
        } 
        tableColumn = domConstruct.create("td",{style: { marginLeft: "auto", marginRight: "auto" }},tableRow); 
        var tnNode = new ArtThumbnailWidget({ 
         art: art, 
         viewerId: this.viewerId, 
         competitionUrlBase: this.newCompetitionUrlBase, 
         competitionButtonIconUrl: this.newCompetitionButtonIconUrl, 
        }); 
        tnNode.placeAt(tableColumn); 
       }); 
      } 
     }); 
}); 

然而,当我运行在Chrome中的新组件,我得到了dojo.js.uncompressed.js线1716的消息一般错误错误是“multipleDefine”,并且附加的Object看起来是我的ArtTableWidget。我在挖掘这个对象时注意到,“deps”成员看起来是顶部define()中定义的所有依赖项的数组,其中包含img/ArtThumbnailWidget,但“pack”成员未定义。我猜测这只是不加载我的模块或其他东西。

错误(对不起,如果复制/粘贴不右看看)是:

dojo.js.uncompressed.js:1716 
Error 
    arguments: undefined 
    get stack: function getter() { [native code] } 
    info: Object 
    cacheId: 0 
    cjs: Object 
    def: function (declare,parser,_WidgetBase,_TemplatedMixin, dom, domConstruct, ArtThumbnailWidget, template) { 
    deps: Array[8] 
    0: Object 
    1: Object 
    2: Object 
    3: Object 
    4: Object 
    5: Object 
    6: Object 
     cacheId: 0 
     def: 0 
     executed: 4 
     injected: 2 
     isAmd: false 
     isXd: null 
     mid: "img/ArtThumbnailWidget" 
     pack: undefined 
     pid: "" 
     result: Object 
     url: "/ArtSite/resources/img/ArtThumbnailWidget.js" 
     __proto__: Object 
    7: Object 
    length: 8 
    __proto__: Array[0] 
    executed: 0 
    injected: 2 
    isAmd: false 
    isXd: null 
    mid: "img/ArtTableWidget" 
    node: HTMLScriptElement 
    pack: undefined 
    pid: "" 
    require: function (a1, a2, a3){ 
    result: Object 
    url: "/ArtSite/resources/img/ArtTableWidget.js" 
    __proto__: Object 
    message: "multipleDefine" 
    set stack: function setter() { [native code] } 
    src: "dojoLoader" 
    type: undefined 
    __proto__: ErrorPrototype 
    dojo.js.uncompressed.js:1719src: dojoLoader 
    dojo.js.uncompressed.js:1719info: 
    Object 
    dojo.js.uncompressed.js:1721. 

我需要一些帮助这里在正确的轨道上找回。

编辑1 我更新了所有使用BuffaloBuffalo的回复信息的模块,除了没有在dojoConfig我用下面的一个“路径”:

<script type="text/javascript"> 
    var djConfig = { 
      parseOnLoad: false, 
      isDebug: false, 
      locale: '${fn:toLowerCase(userLocale)}', 
      packages: [ 
       { name: "message", location: "${message_dojo_module_base_url}" }, 
       { name: "img", location: "${img_dojo_module_base_url}" } 
      ] 
     }; 
    </script> 

似乎找到。 js文件,但不是使用dojo /文本加载的模板。我试过做“./path/Template.html”和“/module/path/Template.html”,但第一个似乎尝试通过CDN(上面链接的Google API网站)解析URL,后者似乎想要一个完全合格的路径。我快门放入一条完整的道路,因为它似乎是一个肮脏的方式来做到这一点。我也尝试添加到dojoConfig路径为这样的:

 paths: [ 
      { "message" : "${message_dojo_module_base_url}" } 
     ] 

但是这似乎并没有在所有帮助,导致Chrome的JS控制台一些非常讨厌的错误。

如果我正确阅读here,不要dojo/text使用模块吗?

+0

您是否解决了这个问题?请提供任何更新! – saravanakumar

+0

对不起,我没有。我最终选择使用jQuery来完成这个项目,因为我永远无法在Dojo世界中弄清楚事情。 – CodeChimp

+0

感谢您的回复:) – saravanakumar

很难告诉确切的问题是什么,但一对夫妇的事情,我跳出:如果您使用的1.7(dojoConfig

djConfig对象应该被命名为dojoConfig仍然有效,但可能以及更新它)。

modulePaths属性应更新为path。如果img.ArtThumbnailWidgetimg.ArtTableWidget驻留在一个公用目录中你可以使用类似:

var dojoConfig = { 
      parseOnLoad: false, 
      isDebug: false, 
      locale: '${fn:toLowerCase(userLocale)}', 
      paths: { 
       "message": "${message_dojo_url}", 
       "img": "${art_module_url}" 
      } 
     }; 

的第二件事是在img.ArtThumbnailWidget混合遗产/ AMD装载机风格。 AMD风格的产品占99%。所有你需要做的是

  1. 删除dojo.provide和dojo.requires
  2. 更新require([],function(){..});define([],function(){..});
  3. 在申报使用的局部变量,而不是全局更新引用:

    //ArtThumbnailWidget 
    define('img/ArtThumbnailWidget', [ 
        "dojo/_base/declare", 
        "dojo/parser", 
        "dojo/ready", 
        "dijit/_WidgetBase", 
        "dijit/_TemplatedMixin", 
        "dojo/dom", 
        "dojo/dom-construct", 
        "dojo/on", 
        "dojo/text!img/ArtThumbnailWidget/templates/ArtThumbnailWidget.html", 
        "dojox/image/LightboxNano", 
        "dojo/domReady!" 
        ], function (declare, parser, ready, _WidgetBase, _TemplatedMixin, dom, domConstruct, on, template) { 
    
        return declare("img.ArtThumbnailWidget", [_WidgetBase, _TemplatedMixin], { 
        /* Our properties will go here */ 
    
        // Art JSON object, default is null 
        art: null, 
    
        // Viewer ID (the username of the person looking at this image), which will default to null 
        viewerId: null, 
    
        // maxThumbnailSize is how large of an image to return for the thumbnail. The back-end will resize the thumbnail accordingly 
        maxThumbnailSize: 100, 
    
        // maxImageSize is how large of an image to return for the LightboxNano. The back-end will resize the image accordingly 
        maxImageSize: 500, 
    
        // Our template - important! 
        templateString: template, 
    
        // A class to be applied to the root node in our template 
        baseClass: "artThumbnailWidget", 
    
        // Specifies there are widgets in the template itself that need to be rendered as well 
        widgetsInTemplate: true, 
    
        // Competition-related vars 
        competitionUrlBase: null, 
        competitionButtonIconUrl: null, 
    
        /* This is called once the DOM structure is ready, but before anything is shown */ 
        postCreate: function() { 
         // Get a DOM node reference for the root of our widget 
         var domNode = this.domNode; 
    
         // Run any parent postCreate processes - can be done at any point 
         this.inherited(arguments); 
    
         if (this.art != null && this.viewerId != null && this.art.owner.name == this.viewerId) { // If the view is the owner, add the toolbar 
         // TODO: We need to clean this up, make it "prettier", and make the URLs more generic 
         var toolbarNode = domConstruct.create("div", {}, this.containerNode); 
    
         if (this.competitionUrlBase != null) { 
          var url = this.competitionUrlBase; 
          if (url.indexOf('?') < 0) { // URL does not have a '?' 
          url = url + "?"; 
          } else { // URL has a '?', so we need to tack on and additional '&' 
          url = url + "&"; 
          } 
          url = url + "username=" + this.art.owner.name + "&artPieceId=" + this.art.id; 
    
          var compButtonNode = domConstruct.create("a", { 
          href: url, 
          }, toolbarNode); 
          var compButtonImg = domConstruct.create("img", { 
          src: this.competitionButtonIconUrl, 
          width: this.maxThumbnailSize/4, 
          height: this.maxThumbnailSize/4, 
          }, compButtonNode); 
         } 
         } 
        }, 
    
        /* This private method is used to re-set the node values when something changes */ 
        _resetNodeValues: function() { 
         if (this.art != null) { 
         // Using our thumbnailNode attach point, set its src value 
         this.thumbnailNode.src = this.art.url + "?maxSize=" + this.maxThumbnailSize; 
         this.thumbnailNode.alt = this.art.title; 
         this.thumbnailNode.width = this.maxThumbnailSize; 
         this.thumbnailNode.height = this.maxThumbnailSize; 
    
         // Now setup the link for the LightboxNano 
         var lightboxNano = new LightboxNano({ 
          href: this.art.url + "?maxSize=" + this.maxImageSize, 
         }, this.thumbnailNode); 
         } 
        }, 
    
        /* This is called anytime the "art" attribute is set. Consider is a "setter" method */ 
        _setArtAttr: function (av) { 
         if (av != null) { 
         // Save it on our widget instance - note that 
         // we're using _set, to support anyone using 
         // our widget's Watch functionality, to watch values change 
         this._set("art", av); 
    
         this._resetNodeValues(); 
         } else { 
         // We could have a default here...would be an error, since we 
         // shouldn't be calling this without an art object 
         } 
        }, 
    
        _setMaxThumbnailSizeAttr: function (ms) { 
         // Save it on our widget instance - note that 
         // we're using _set, to support anyone using 
         // our widget's Watch functionality, to watch values change 
         this._set("maxThumbnailSize", ms); 
    
         this._resetNodeValues(); 
        }, 
    
        _setMaxImageSizeAttr: function (ms) { 
         // Save it on our widget instance - note that 
         // we're using _set, to support anyone using 
         // our widget's Watch functionality, to watch values change 
         this._set("maxImageSize", ms); 
    
         this._resetNodeValues(); 
        } 
        }); // End of the widget 
    }); 
    

我怀疑与AMD的风格传统风格ArtThumbnailWidget组合是WH在迷惑ArtTableWidget

+0

djConfig是旧名称。 dojoConfig是新名称。请参阅http://dojotoolkit.org/documentation/tutorials/1.7/dojo_config/。 –

+0

我在输入答案时查看了确切的页面。自从代码片段正确后,必须在编写代码时切换。更新我的答案以保持一致。 – BuffaloBuffalo

+0

感谢BuffaloBuffalo。我接受了你的建议,改变了我的习惯组件,现在至少转移到了另一个问题。我得到了与上面类似的错误,但是现在在CDN的dojo/parser中。另外,当我使用dojo /文本时,它似乎无法找到我的本地模板文件!插件...它试图解析“./”到CDN网址。我尝试着在前面的模块名称上,但它似乎根本不使用模块。尽管如此,我仍然在尝试一些事情,并会回报。 – CodeChimp

所以,是的,这里有很多东西可能是错误的。你能得到一个更小的例子来工作吗?

  1. 绝对值得一试的浏览器开发者工具的“网络”标签,看什么它试图加载。这通常有助于模块分辨率。同步运行(我认为你是),而不是异步模式也有助于诊断。
  2. 你应该注册img/ArtThumbnailWidget在你的modulePaths而不是img.ArtThumbnailWidget?
  3. 长期来看,您可能希望注册软件包而不是逐个模块...
  4. 您应该能够参考dojo/text!./ templates/ArtThumbnailWidget.html而不是dojo/text!img /ArtThumbnailWidget/templates/ArtThumbnailWidget.html在你的小部件中,但只有在加载小部件后才会变得相关。 (您的模块需求是相对于您的模块进行处理的。)