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.
Related
hey guys i am very new to js and jquery in genenral and i was just going throught the plugin code of a gallery plugin , i can across the function called _loadevents , that had the following content , see below :
this.$navPrev.on('click.gallery', function (event) {
});
this.$navNext.on('click.gallery', function (event) {
});
this.$wrapper.on('webkitTransitionEnd.gallery transitionend.gallery OTransitionEnd.gallery', function (event) {
});
now $navPrev , $navNext , and $wrapper are obviously some HTML element , now my question is about another method i came across in the same plugin , look below :
destroy: function () {
// console.log('inside destroy');
this.$navPrev.off('.gallery');
this.$navNext.off('.gallery');
this.$wrapper.off('.gallery');
}
now i see that if this function is called all the event handlers will be taken off. now , can somebody tell me what is the necessacity of such a function , does it improve a plugins efficiency ? how or when does such a function get used and is it a common practice to write e destroy function for events in plugins ?
Thank you.
Alex-z .
Destroy functions in plugins enable a developer to reset or remove a plugin from an element, restoring the element to before the plugin was initialised. This is useful if, for example, you have a gallery plugin that works and looks fantastic on desktop, but you don't want it on mobile. You can listen to resize event on window and if the window size is smaller than e.g. 710px then destroy the plugin. This will remove all the added events, undo any DOM manipulation, and restore the html elements back to how they were before the plugin was first initialised (turn-wise, if the window size is larger than 710px then initialise the plugin).
They are generally considered good practice.
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.
I'm using jQuery with the bxSlider plugin, here is the link to it just incase: http://bxslider.com/
I'm trying to reload the slider and my custom pager after I've removed certain slides from it.
Here is what I have tried:
$(function() {
var slider = $('#slider').bxSlider({
pagerCustom: '#bx-pager'
});
$('.list').on('click', '.delete', function() {
image = $(this).closest('li').find('[type="hidden"]');
// image.attr('id') contains a string: image-0, image-1, image-2, etc.
$('#slider, #bx-pager').find('.' + image.attr('id')).remove();
slider.reloadSlider({
pagerCustom: '#bx-pager'
}); // I have also tried: slider.reloadSlider();
});
});
It works partially. What happens is the slider gets reloaded just fine but it removes the pager completely when it runs the reload.
Thank you very much for any help.
As long as I see, this is a bug in bxSlider, in fact, when you call the reloadSlider method, internally are called the methods destroySlider and init.
In the destroySlider method the pagerEl element is destroyed, this is right if you are not using a custom one, because it is recreated programmatically in the init method, but if you are using a custom one it can't be recreated programmatically.
I ended up modifying the destroySlider method to check if a custom pager is used, in this case it must not be deleted.
Here is the before (line 1294):
if(slider.pagerEl) slider.pagerEl.remove();
And after:
if (slider.settings.pagerCustom === '') {
if(slider.pagerEl) slider.pagerEl.remove();
}
I'll post the bug on GitHub as soon as I have the time.
I have made a webform that uses a TinyMCE editor. When the user clicks on a link to leave the page, I want a message to be displayed if he still has unsaved changes. For this, I was thinking of using the TinyMCE undoManager, http://www.tinymce.com/wiki.php/API3:class.tinymce.UndoManager
Essentially, I want the events onAdd, onUndo, OnRedo to fire. I will then keep track of the number of changes (if any) since the last save. But how do I get them to fire? Where do I set them up?
Also, it would be nice to have access to the hasUndo method in the rest of my javascript code. Again, not sure where to initiate this?
Not sure if it matters, but I'm using Django.
Edit: I have tried
tinyMCE.init({
...,
setup : function(ed) {
ed.UndoManager.onAdd(function(ed) {
ed.windowManager.alert('added.');
});
}
});
This gives me an error: Unable to get value of the property 'onAdd': object is null or undefined
I created a tinym fiddle for this: http://fiddle.tinymce.com/H0caab .
The solution is to use the oninit setting and to addresss the onAdd.add:
tinyMCE.init({
...
setup : function(ed) {
ed.onInit.add(function(ed) {
ed.undoManager.onAdd.add(function(ed) {
alert('added.');
});
});
}
});
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.