I'm opening a Backbone view in a Zurb Foundation Reveal (Modal) section.
this.$('#ChangeIconModal').html( this.editIconView.render().el );
This works fine the first time. However, if I close it (either by clicking it, or by calling $('#ChangeIconModal').foundation('reveal', 'close')), the click event I have set up no longer fire.
Here is how I've set up my click event:
events: { 'click button.finish': 'finish', 'click a.close-reveal-modal': 'close' }
And, regardless of how the close happens, I remove the Backbone view when I'm done with it:
this.remove();
Does anything seem obviously wrong with what I'm doing?
PS - I'm new to the whole Backbone/Zurb world, so bear with me. If you need any more information, I'll be glad to provide it, I just don't know what to provide.
Ahh, I figured it out. Here's what I did, in case anyone else comes across the same issue.
Here's what I had before in my view:
initialize: function() {
// Other initialize code here...
this.editIconView = new IconEditView({ model: this.model });
}
iconEdit: function() {
this.$('#SubtabEditModal').html( this.editIconView.render().el );
}
However, because I called remove on it later, the reference to editIconView was no longer valid.
I had to change my code to be more like this:
initialize: function() {
// Other initialize code here...
}
iconEdit: function() {
this.editIconView = new IconEditView({ model: this.model });
this.$('#SubtabEditModal').html( this.editIconView.render().el );
}
It seems to be working now. If this isn't clear, leave a comment, I'll try to help.
Related
I am extending a cloud-hosted LMS with javascript. Therefore, we can add javascript to the page, but cannot modify the vendor javascript for different components.
The LMS uses tinyMCE frequently. The goal is to add a new button on to the toolbar of each tinyMCE editor.
The problem is that since the tinyMCE modules are initialized in the vendor's untouchable code, we cannot modify the init() call. Therefore, we cannot add any text on to the "toolbar" property of the init() object.
So I accomplished this in a moderately hacky way:
tinyMCE.on('AddEditor', function(e){
e.editor.on('init', function(){
tinyMCE.ui.Factory.create({
type: 'button',
icon: 'icon'
}).on('click', function(){
// button pressing logic
})
.renderTo($(e.editor.editorContainer).find('.mce-container-body .mce-toolbar:last .mce-btn-group > div')[0])
});
});
So this works, but needless to say I am not totally comfortable having to look for such a specific location in the DOM like that to insert the button. Although this works, I do not believe it was the creator's intention for it to be used like this.
Is there a proper way to add the button to a toolbar, after initialization, if we cannot modify the initialization code?
I found a more elegant solution, but it still feels a bit like a hack. Here is what I got:
// get an instance of the editor
var editor=tinymce.activeEditor; //or tinymce.editors[0], or loop, whatever
//add a button to the editor buttons
editor.addButton('mysecondbutton', {
text: 'My second button',
icon: false,
onclick: function () {
editor.insertContent(' <b>It\'s my second button!</b> ');
}
});
//the button now becomes
var button=editor.buttons['mysecondbutton'];
//find the buttongroup in the toolbar found in the panel of the theme
var bg=editor.theme.panel.find('toolbar buttongroup')[0];
//without this, the buttons look weird after that
bg._lastRepaintRect=bg._layoutRect;
//append the button to the group
bg.append(button);
I feel like there should be something better than this, but I didn't find it.
Other notes:
the ugly _lastRepaintRect is needed because of the repaint
method, which makes the buttons look ugly regardless if you add new
controls or not
looked in the code, there is no way of adding new controls to the
toolbar without repainting and there is no way to get around it
without the ugly hack
append(b) is equivalent to add(b).renderNew()
you can use the following code to add the button without the hack, but you are shortcircuiting a lot of other stuff:
Code:
bg.add(button);
var buttonElement=bg.items().filter(function(i) { return i.settings.text==button.text; })[0];
var bgElement=bg.getEl('body');
buttonElement.renderTo(bgElement);
So I am trying to avoid JQUERY UI or really any libraries JS wise and am trying to create some drag and drop functionality in backbone.JS. I've already been able to have some success as you can see at www.smartkrawl.com on the left side but cannot get tables to move in the canvas section. Here is a snippet of code that listens for a mousedown event to execute a draggable function but if you view the source code of the site the JS files, particularly ocoa-tables.js, are available. Any help would be GREATLY appreciated.
var Table = Backbone.Model.extend({
initialize:function(options){
this.set("x",options.x);
this.set("y",options.y);
this.set("el",options.el);
$('body').on('mousedown','.table', function() {
console.log('mousedown')
});
}
});
You probably should use view for this instead of model. So make each table as a separate view, then use events hash to add listeners instead of delegating it on the body
var TableView = Backbone.View.extend({
events: {
"mousedown": "_onMouseDown"
},
_onMouseDown: function(e) {
console.log('mousedown')
}
});
var firstTable = new TableView({ el: ".first.table" });
var secondTable = new TableView({ el: ".second.table" });
I'm not familiar with backbone.js though I do feel like I have a decent grasp on jQuery. I hope I'm not asking an obvious question, though if it's the table that you want, why not directly target the table?
$(".table").on("mousedown", function() {
...
});
I'm using bootstrap3-dialog library from https://nakupanda.github.io/bootstrap3-dialog/
The problem is, everytime the dialog shows (alert, confirm or custom dialog), the body's scrollbar is gone and never come back when dialog closed. I could add this line on every dialog's onhide property, but that would be time consuming:
$('body').css('overflow','scroll')
Is there any other way to trigger that function every time the modal closes?
I was going through the code of bootstrap modal and they have this:
resetScrollbar: function() {
var openedDialogs = this.getGlobalOpenedDialogs();
if (openedDialogs.length === 0) {
this.$body.css('padding-right', BootstrapDialogModal.ORIGINAL_BODY_PADDING);
}
},
Which is called on:
hideModal: function() {
this.$element.hide();
this.backdrop($.proxy(function() {
var openedDialogs = this.getGlobalOpenedDialogs();
if (openedDialogs.length === 0) {
this.$body.removeClass('modal-open');
}
this.resetAdjustments();
this.resetScrollbar();
this.$element.trigger('hidden.bs.modal');
}, this));
}
I can't seem to figure out what would cause this code to not bring the scrollbar back. It seems to be working fine on their website.
If you are comfortable, I would suggest debugging the hideModal function of the api itself and figure out why it is not working and maybe put the above css snippet in there as a work around.
Or maybe post your code on plunkr, jsfiddle so we can look at what is going on.
I'm using hammer.js for gesture functionality on my web application. I have used it to swipe a video element and it works perfect as expected. However, when I apply the following code to an image element it's not working.
App.Views.Photo = Backbone.View.extend({
template : template('photoTemplate'),
className : 'photo',
parent : null,
events: {
'swipe' : 'swiped',
// 'pan' : 'dragged'
},
...
swiped: function(e) {
this.remove();
this.parent.newContent(this.model);
},
This exact same code is working for the video elements but not for the images. I also tried doing e.gesture.preventDefault(); inside the swiped function but that didn't work either. I'm testing the application on firefox at the moment.
Any help will be appreciated.
Thanks
[EDIT]: I'm initializing the hammer code as follows
render: function() {
$(this.el).attr('id', this.model.attributes._id);
this.$el.html( this.template( this.model.toJSON() ) );
this.$el.hammer();
return this;
},
You can use:
<img draggable="false"...
Or in CSS like this (May not be supported by all browsers, esp IE)
pointer-events: none;
Ok, so after banging my head on this problem for weeks I finally got the answer.
in the initialize function I placed the following code
$('img').on('dragstart', function(event) { event.preventDefault(); });
So it looks like this
initialize: function(opts) {
this.render();
this.parent = opts.parent;
$('img').on('dragstart', function(event) { event.preventDefault(); });
},
What this does is that it prevents the image from being dragged like default and that did the trick.
And now on swipe the image gets removed like I wanted.
[EDIT]
If you have multiple images on the page add this to the event like
this.$('img').on('dragstart', function(event) { event.preventDefault(); });
This will apply to all of the picture that are rendered with that view.
When using tinyMCE in a jqueryUI modal dialog, I can't use the hyperlink or 'insert image' features.
Basically, after lots of searching, I've found this:
http://www.tinymce.com/develop/bugtracker_view.php?id=5917
The weird thing is that to me it seams less of a tinyMCE issue and more of a jqueryUI issue since the problem is not present when jqueryUI's modal property is set to false.
With a richer form I saw that what happens is that whenever the tinyMCE loses focus, the first element in the form gets focus even if it's not the one focused / clicked.
Does some JavaScript guru have any idea how I might be able to keep the dialog modal and make tinyMCE work?
This fixed it for me when overriding _allowInteraction would not:
$(document).on('focusin', function(e) {
if ($(event.target).closest(".mce-window").length) {
e.stopImmediatePropagation();
}
});
I can't really take credit for it. I got it from this thread on the TinyMCE forums.
(They have moved their bugtracker to github. tinymce/issues/703 is the corresponding github issue.)
It seems there are no propper solution for this issue yet. This is kind of a hack but it really worked for me.
Every time you open the Dialog remove the text area and re add it like following,
var myDialog = $('#myDialog');
var myTextarea = myDialog.find('textarea');
var clonedTextArea = myTextarea.clone(); // create a copy before deleting from the DOM
var myTextAreaParent = myTextarea.parent(); // get the parent to add the created copy later
myTextarea.remove(); // remove the textarea
myDialog.find('.mce-container').remove(); // remove existing mce control if exists
myTextAreaParent.append(clonedTextArea); // re-add the copy
myDialog.dialog({
open: function(e1,e2){
setTimeout(function () {
// Add your tinymce creation code here
},50);
}
});
myDialog.dialog('open');
This seems to fix it for me, or at least work around it (put it somewhere in your $(document).ready()):
$.widget('ui.dialog', $.ui.dialog, {
_allowInteraction: function(event) {
return ($('.mce-panel:visible').length > 0);
}
});