I'm not sure why I can't get the button element using my UI hash. This is what my Layout looks like:
Layout: App.Base.Objects.BaseLayout.extend({
// Rest of the code left out for brevity
ui: {
btnSave: "#btnSave"
},
events: {
"click #ui.btnSave": "onSave"
},
onInitialize: function () {
this.listenTo(App.vent, "DisableSaveButton", function(val) {
this.disableSaveButton(val);
},this);
},
disableSaveButton: function () {
this.ui.btnSave.prop("disabled",val).toggleClass("ui-state-disabled",val);
},
onSave: function () {
alert("saved!");
}
})
In VS2013, when my breakpoint hits the line inside disableSaveButton method, I entered $("#btnSave") into the Watch window and I was able to get the element back. I could tell because it had a length of 1. From this, I know the button is rendered. However, if I enter this.ui.btnSave into the Watch window, I would get an element with length of 0.
My BaseLayout object is basically a custom object extended from Marionette.Layout
Marionette version: 1.8.8
Any ideas why I can't find the button element using this.ui.btnSave?
Thanks in advance!
Got some help from a coworker and the issue might be because the element is out of scope. Basically, inside the Layout object, 'this' does not contain the element. We were able replace 'this.ui.btnSave' with '$("#btnSave",this.buttonset.el)' and that works fine. buttonset is the region that actually contains the html element.
This seems like an inconsistency because even though the ui hash didn't work, the click event utilizing the ui hash did work.
UPDATE 6/3/2015:
Another coworker of mine provided a better solution. Basically, in my Layout I use a display function to display my view. It looks something like this:
Layout: App.Base.Objects.BaseLayout.extend({
// Rest of the code left out for brevity
display: function() {
$(this.buttonset.el).html(_.template($("#buttonset-view").html(), {"viewType": viewType}));
}
})
Basically, I'm saying to set the html of my region, which is this.buttonset.el, to my template's html. As of now, my layout doesn't know any of the elements inside the region. It just contains a region which displays the elements. So there is some sort of disconnect between my layout and the elements in my region.
The correct solution, as opposed to my earlier workaround, is to simply add the following line of code at the end:
this.bindUIElements();
From Marionette Annotated Source:
This method binds the elements specified in the “ui” hash inside the
view’s code with the associated jQuery selectors.
So this final code looks like this:
Layout: App.Base.Objects.BaseLayout.extend({
// Rest of the code left out for brevity
display: function() {
$(this.buttonset.el).html(_.template($("#buttonset-view").html(), {"viewType": viewType}));
this.bindUIElements();
}
})
With this, I was able to finally able to retrieve my element using this.ui.btnSave.
Related
After creating and rendering a Kendo UI TreeView to fill a DIV, repeat invocation alternately renders only "loading..." or works properly. Since I am having possibly similar problems with Kendo UI ContextMenu, I speculate there may be some required cleanup in between, which is passively done by even invocations such that odd invocations work, but I can't figure it out (a link to Kendo UI docs I might be missing so I can understand why I've missed this would be appreciated to help with other issues).
In my JSFiddle example, click "draw" over and over and you'll see the alternate behavior. Speculatively clicking "draw, destroy, draw, destroy..." does not seem to help.
https://jsfiddle.net/rk3nfnnu/
<script>
function TreeDestroy() { // http://stackoverflow.com/questions/5431351
$('#Tree_Space').data('kendoTreeView').destroy();
alert('destroyed');
}
function TreeShow() {
$('#Tree_Space').kendoTreeView({
dataSource: [ { Name: 'Top', items: [ { Name:'Item' } ] } ],
template: kendo.template($('#Tree_template').html())
});
alert('shown');
}
</script>
draw |
destroy
<div id='Tree_Space'>
</div>
<script type='text/x-kendo-template' id='Tree_template'>
#= item.Name#
</script>
I have updated that fiddle. The destroy(); method probably only destroys allocated dom elements after the widget was rendered (the nodes). I doubt it cleans up the wrappers and whatnot. In your TreeDestroy(), issue a clear on that element div. Of course, you should call TreeDestroy prior to TreeCreate just in case.
function TreeDestroy() { // http://stackoverflow.com/questions/5431351
$('#Tree_Space').data('kendoTreeView').destroy();
$('#Tree_Space').html('');
alert('destroyed');
}
Here is some kendoui documentation that refers to how to handle manual deletion of widgets.
My ember app is set up with a list of posts on the left and a view for an individual post on the right. When one of the posts on the left is clicked it's content is rendered in the view on the right.
This is the code I'm using to add syntax highlighting to a post.
App.PostView = Ember.View.extend({
didInsertElement: function() {
$('pre code').each(function(i, e) {hljs.highlightBlock(e)});
}
});
When the first post view is rendered, it has the syntax highlighting, but when I click on a different post and it's content gets loaded into the post view the syntax highlighting does not get applied. How can I make it so that the highlighting applied every time a post is rendered?
I can only guess without a more comprehensive example. Is PostView what gets created in the right panel? If so, then you need to constrain your view rendering to the stuff inside the view.
In your example, $('pre code') will target all pre code elements inside the document. Try this.$('pre code'), or whatever element/selector needs to be highlighted within the view.
This may be not the cleanest way to do the job, but you could try adding observer to the controller's model, and make required changes. But this will only work, if the model itself changes.
Like this:
postHasChanged: function() {
if (this.get('state') === 'inDOM') {
$('pre code').each(function(i, e) {
hljs.highlightBlock(e)
});
}
}.observes('controller.model')
EDIT: This could be seen as a pure javascript objects question. The code can be found here:
jquery.mobile-1.1.0.js
I need to access properties of a jQuery mobile JS-object but is not sure how that is possible. In the jquery.mobile-1.1.0.js and mobile.slider is the following (see extend on line 5967):
$.widget( "mobile.slider", $.mobile.widget, {
...
_create: function() {
...
$.extend( this, {
slider: slider,
handle: handle,
valuebg: valuebg,
dragging: false,
beforeStart: null,
userModified: false,
mouseMoved: false
});
Primarily the property I would like to read is the "dragging".
I know i can execute the methods using:
$("#slider").slider("refresh")
Is there a similair way to access the properties?
Thanks
How to react to user dragging the slider, without having to bind mouse-/tap-events, but instead using the JQM functionallity already in place.
To access the "dragging" variable of the JQM slider object I made an extension to the object as follows:
$(document).bind("mobileinit", function(){
$.mobile.slider.prototype.getDragging = function(){
return this.dragging;
};
});
With that in place, I can choose to react to changes only done by the user:
$("#slider").live('change',function(){
if($("#slider").slider("getDragging"))){
console.log('User is dragging slider to new value');
}
else {
console.log('Program changed value. (or user typed in visible textbox)') ;
}
});
With the slider textbox hidden, this give me the benefit of:
Using the "change"-event to react to user dragging without being triggered when my program change the slider value.
When my program is going to change the slider value, it can first check that the user is NOT currently dragging the slider.
I'm using ExtJS 3.2.1 and I need a component almost identical to the bundled HtmlEditor, with one exception: it must start editing the HTML source code directly. The reason I don't use a normal TextArea is that the user should be able to preview the result of his actions before submitting.
I've tried calling toggleSourceEdit(), as per ExtJS documentation, with no success. Debugging, I see that the editor object has the sourceEditMode property set to true, and the Source Edit button seems as if it was "pressed", but clicking on it does not render the typed HTML, and clicking it again goes to the Source Mode.
I've tried calling toggleSourceEdit() after the container show() method, on the container afterLayout listener and on the editor afterRender listener. I've tried also calling it on another button that I added to the container. The result is the same on every try.
The only other option I see is updating ExtJS to 3.3.0, but I haven't seem anything related on the changelogs. Either way, it's going to be my next step. EDIT: The app had another problems when updating, we'll make a bigger effort to update later. As of right now, we are using the HtmlEditor in its original setting.
Thanks!
ran into the same problem (using 3.3.0 by the way)
stumbled upon a fix by dumb luck. i have no idea why this works, but second time is the charm. call it twice in a row to achieve the desired effect..
HTMLEditor.toggleSourceEdit(true);
HTMLEditor.toggleSourceEdit(true);
hope that helps!
Rather calling toggleSourceEdit(), try to setup the configuration while you create HtmlEditor Object
Using toggleSourceEdit() caused some problems for me. One was that this seemed to put the editor somewhere in limbo between source edit and WYSIWYG mode unless I used a timeout of 250ms or so. It also puts the focus in that editor, and I don't want to start the form's focus in the editor, especially since it's below the fold and the browser scrolls to the focused html editor when it opens.
The only thing that worked for me was to extend Ext.form.HtmlEditor and then overwrite toggleSourceEdit, removing the focus command. Then adding a listener for toggling to the source editor when the component is initialized. This is for Ext 4.1 and up. For older versions, replace me.updateLayout() with me.doComponentLayout().
var Namespace = {
SourceEditor: Ext.define('Namespace.SourceEditor', {
extend: 'Ext.form.HtmlEditor',
alias: 'widget.sourceeditor',
initComponent: function() {
this.callParent(arguments);
},
toggleSourceEdit: function (sourceEditMode) {
var me = this,
iframe = me.iframeEl,
textarea = me.textareaEl,
hiddenCls = Ext.baseCSSPrefix + 'hidden',
btn = me.getToolbar().getComponent('sourceedit');
if (!Ext.isBoolean(sourceEditMode)) {
sourceEditMode = !me.sourceEditMode;
}
me.sourceEditMode = sourceEditMode;
if (btn.pressed !== sourceEditMode) {
btn.toggle(sourceEditMode);
}
if (sourceEditMode) {
me.disableItems(true);
me.syncValue();
iframe.addCls(hiddenCls);
textarea.removeCls(hiddenCls);
textarea.dom.removeAttribute('tabindex');
//textarea.focus();
me.inputEl = textarea;
} else {
if (me.initialized) {
me.disableItems(me.readOnly);
}
me.pushValue();
iframe.removeCls(hiddenCls);
textarea.addCls(hiddenCls);
textarea.dom.setAttribute('tabindex', -1);
me.deferFocus();
me.inputEl = iframe;
}
me.fireEvent('editmodechange', me, sourceEditMode);
me.updateLayout();
}
})
}
Then to use it:
Ext.create('Namespace.SourceEditor', {
/*regular options*/
listeners: {
initialize: function(thisEditor) {
thisEditor.toggleSourceEdit();
}
}
});
htmlEditor.toggleSourceEdit(true);
one time should be enough if you do this listening to the afterrender event of the editor.
i have an custom widget in dojo. My Problem is to check some kind of access rules wich are passed to the widget.
if check the rules after the widget is fully loaded everything works fine. But i have to remove some text and buttons before it is displayed.
I've tryted the startup, and postcreate hook (-: is there something like "aftercreate" ?
The first solution I can think of is to begin with hiding the restricted elements and then remove them.
In css:
.hidden{ display: none }
In widget's template for all permissions-sensitive elements:
<div class="${permissionsSensitiveElementsClass}">...</div>
In widget's code:
permissionsSensitiveElementsClass: "",
postMixInProperties: function(){
if(!this.hasPermissions()){
this.permissionsSensitiveElementsClass = "hidden";
}
this.inherited(arguments);
},
startup: function(){
// remove elements if necessary
},
hasPermissions: function(){
// permissions check
},
The final rendering function would be startup(). For widgets which are initially hidden, startup gets called automatically when call is made to show(). dijit.layout.Container has 'addChild(widget)' functionality, which will fire widget.startup() when a/multiple child(ren) are added.
You would benifit from:
http://dojotoolkit.org/documentation/tutorials/1.6/understanding_widget/
Widget lifecycle:
([widget].constructor());
[widget].postscript();
[widget].create();
[widget].postMixinProperties();
[widget].buildRendering();
[widget].postCreate(); // this is the most important one!
[widget].startup();
The true answer to your question lies here;
dojo.declare("mydijit", ["dijit/_Widget"], {
startup: function() {
// call superclass functionality before applying hide on specific elements
this.inherited(arguments);
if(foo) dojo.destroy(this.fooNode);
if(bar) dojo.destroy(this.barNode);
},
onShow: function() {
if(foo.changed || bar.changed) {
// act upon it
}
}
}