How to jQuery bindings with a Backbone View - javascript

I have a Backbone view, Inside that view there's an input that uses twitters typeahead plugin. My code works, but I'm currently doing the typeahead initialisation inside the html code and not in my Backbone code.
TypeAhead.init('#findProcedure', 'search/procedures', 'procedure', 'name', function(suggestion){
var source = $("#procedure-row-template").html();
var template = Handlebars.compile(source);
var context = {
name: suggestion.name,
created_at: suggestion.created_at,
frequency: suggestion.frequency.frequency,
urgency: suggestion.urgency.urgency,
id: suggestion.id
};
var html = template(context);
AddRow.init("#procedure-table", html);
});
The code above is what works inside script tag.
But when I try taking to backbone it doesn't work.
What I'm trying in my BB code is:
initialize: function(ob) {
var url = ob.route;
this.render(url);
this.initTypeahead();
this.delegateEvents();
},
And obviously inside the init function there's the code that works, but not in BB. What could be wrong ? Is this a correcto approach ?
Thanks.

Related

How to append a breadcrumb to jQuery function

I have a function which has breadcrumbs
_constructBreadCrumb : function(){
$.ui.breadcrumb = $('<ul class="testBreadCrumb"><li><a class ="TestCodeView" href="#testCodeView">CodeTest</a></li></ul>');
},
Then I have another function which appends the breadcrumbs and some other functionalities
_constructApp : function(container) {
var widget = this;
$('<ul/>').appendTo(container)
.append($._constructBreadCrumb)
.append('<li><a class="layoutViewButton" href="#layoutView"><i>Layout</i></a</li>')
.append('<li><a class="codeViewButton" href="#codeView"><i>Code</i></a></li>')
.append('<li><a class="liveViewButton" href="#liveView"><i>Preview</i></a></li>');
//more code to load the rest of the features
I am not able to load the breadcrumb when I add append. I'm sure I'm doing something wrong.
PS: I am new to jQuery.

Backbone.Marionette Layout: Access region.layout.view directly

I have a Marionette application which as more than 1 region.
App.addRegions({
pageRegion: '#page',
contentsRegion :'#contents'
});
As part of App.pageRegion, I add a layout.
App.ConfiguratorLayout = Marionette.Layout.extend({
template: '#configurator-page',
regions: {
CoreConfiguratorRegion: '#Core-Configurator-Region',
SomeOtherRegion:'#someOtherregion'
}
});
This layout is rendered before the application starts.
App.addInitializer(function() {
var configLayout = new App.ConfiguratorLayout();
App.pageRegion.show(configLayout);
});
Later on in the application, I just need to change the contents of the configLayout.
I am trying to achieve something like this.
App.pageRegion.ConfiguratorLayout.CoreConfiguratorRegion.show(someOtherLayout);
Is there a way to do this besides using DOM selector on the $el of App.pageRegion.
App.pageRegion.$el.find('#...')
Instead of in an app initializer, move the configLayout initialization code into a controller that can keep a reference to it and then show() something in one of its regions.
// pseudocode:
ConfigController = Marionette.Controller.extend({
showConfig: function() {
var layout = new App.ConfiguratorLayout();
App.pageRegion.show(configLayout);
var someOtherLayout = new App.CoreConfiguratorLayout();
layout.coreConfiguratorRegion.show(someOtherLayout);
// ... maybe create and show() some views here?
}
});
App.addInitializer(function() {
var controller = new ConfigController();
// more likely this would be bound to a router via appRoutes, instead of calling directly
controller.showConfig();
});

Backbone events not firing on new element added to DOM

I'm using a combination of handlebars and Backbone. I have one "container" view which has an array to hold child views. Whenever I add a new view, click events are not being bound.
My Post View:
Post.View = Backbone.View.extend({
CommentViews: {},
events: {
"click .likePost": "likePost",
"click .dislikePost": "dislikePost",
"click .addComment button": "addComment"
},
render: function() {
this.model.set("likeCount", this.model.get("likes").length);
this.model.set("dislikeCount", this.model.get("dislikes").length);
this.$('.like-count').html(this.model.get("likeCount") + " likes");
this.$('.dislike-count').html(this.model.get("dislikeCount") + " dislikes");
return this;
}, ...
My callback code in the "container" view which creates a new backbone view, attaches it to a handlebars template and shows it on the page:
success: _.bind(function(data,status,xhr) {
$(this.el).find("#appendedInputButton").val('');
var newPost = new Post.Model(data);
var newPostView = new Post.View({model: newPost, el: "#wall-post-" + newPost.id});
var source = $("#post-template").html();
var template = Handlebars.compile(source);
var html = template(newPost.toJSON());
this.$('#posts').append(html);
newPostView.render();
this.PostViews[newPost.id] = newPostView;
}, this), ...
Not sure what's going on, but this sort of code is run initially to set up the page (sans handlebars since the html is rendered server-side) and all events work fine. If I reload the page, I can like/dislike a post as well.
What am I missing?
I dont see you appending newPostView.render().el to dom .Or am i missing somehting?
Assuming the "#post-template" contains the "likePost" button. The newPostView is never added to the DOM.
Adding el to the new Post.View makes backbone search the DOM (and the element won't exist yet)
4 lines later a HTML string is added to the DOM (assuming the this.el is already in the DOM)
If you create the Post.View after the append(html) the element can be found and events would be fireing.
But the natural Backbone way would be to render the HTML string inside the Post.View render function, append the result to it's el and append that el to the #posts element.
success: function (data) {
var view = new Post.View({model: new Post.Model(data)});
this.$('#posts').append(view.render().el);
this.PostViews[data.id] = view;
}

TypeError: this.$E_0.getElementsByTagName is not a function

I am attempting to create a modal dialog in sharepoint 2010, but I'm getting this error:
TypeError: this.$E_0.getElementsByTagName is not a function
my code is:
var options = SP.UI.$create_DialogOptions();
options.html = '<div class="ExternalClass23FFBC76391C4EA5A86FC05D3D9A1904"><p>RedConnect is now available.​</p></div>';
options.width = 700;
options.height = 700;
SP.UI.ModalDialog.showModalDialog(options);
using firebug, i tried simply using the url field instead of the html field and it gave no error.
also related to this, what does SP.UI.$create_DialogOptions() actually do? what is the difference between using it and simply using a dict of values for your options?
options.html requires a HTML DOM element instead of plain HTML code:
<script>
function ShowDialog()
{
var htmlElement = document.createElement('p');
var helloWorldNode = document.createTextNode('Hello world!');
htmlElement.appendChild(helloWorldNode);
var options = {
html: htmlElement,
autoSize:true,
allowMaximize:true,
title: 'Test dialog',
showClose: true,
};
var dialog = SP.UI.ModalDialog.showModalDialog(options);
}
</script>
Boo
Example code taken from the blog post Rendering html in a SharePoint Dialog requires a DOM element and not a String.
also related to this, what does SP.UI.$create_DialogOptions() actually do? what is the difference between using it and simply using a dict of values for your options
When you look at the definition of the SP.UI.DialogOptions "class" in the file SP.UI.Dialog.debug.js you see that its a empty javascript function.
SP.UI.DialogOptions = function() {}
SP.UI.$create_DialogOptions = function() {ULSTYE:;
return new SP.UI.DialogOptions();
}
My guess is that it is there for client diagnostic purpose. Take a look at this SO question: What does this Javascript code do?

jquery templating - import a file?

I'm working with backbone.js, but as far as I've seen, it doesn't care what templating system you use. Currently I'm trying out mustache.js, but I'm open to other ones. I'm a little annoyed though with the way I have to put a template into a string:
var context = {
name: this.model.get('name'),
email: this.model.get('email')
}
var template = "<form>Name<input name='name' type='text' value='{{name}}' />Email<input name='email' type='text' value='{{email}}' /></form>";
var html = Mustache.to_html(template, context);
$(this.el).html(html);
$('#app').html(this.el);
I'd like if I could load it from a different file or something somehow. I want to be able to have template files in order to simplify things. For example, if I put it all in a string, I can't have breaks (well I can have html breaks, but that's not the point). After the line starts to get very long, it becomes unmanageable.
Tips?
Updated (4/11/14):
As answered by OP below:
Unfortunately, the jQuery team has moved the templating functionality out of jQuery Core. The code is still available as a library here: github.com/BorisMoore/jquery-tmpl and here: github.com/borismoore/jsrender
Original Answer:
I just used this a couple of hours ago:
http://api.jquery.com/category/plugins/templates/
It's an official jQuery plugin(i.e. the devs endorse it).
This is the function you need to use for loading templates from things other than strings: http://api.jquery.com/template/
Here's the code to have a template in HTML:
<script id="titleTemplate" type="text/x-jquery-tmpl">
<li>${Name}</li>
</script>
___________
// Compile the inline template as a named template
$( "#titleTemplate" ).template( "summaryTemplate" );
function renderList() {
// Render the movies data using the named template: "summaryTemplate"
$.tmpl( "summaryTemplate", movies ).appendTo( "#moviesList" );
}
It's in a <script> tag, because that's not visible by default.
Note the type="text/x-jquery-tmpl". If you omit that, it will try to parse it as JavaScript(and fail horribly).
Also note that "loading from a different file" is essentially the same as "reading a file" and then "loading from a string".
Edit
I just found this jQuery plugin - http://markdalgleish.com/projects/tmpload/ Does exactly what you want, and can be coupled with $.tmpl
I have built a lightweight template manager that loads templates via Ajax, which allows you to separate the templates into more manageable modules. It also performs simple, in-memory caching to prevent unnecessary HTTP requests. (I have used jQuery.ajax here for brevity)
var TEMPLATES = {};
var Template = {
load: function(url, fn) {
if(!TEMPLATES.hasOwnProperty(url)) {
$.ajax({
url: url,
success: function(data) {
TEMPLATES[url] = data;
fn(data);
}
});
} else {
fn(TEMPLATES[url]);
}
},
render: function(tmpl, context) {
// Apply context to template string here
// using library such as underscore.js or mustache.js
}
};
You would then use this code as follows, handling the template data via callback:
Template.load('/path/to/template/file', function(tmpl) {
var output = Template.render(tmpl, { 'myVar': 'some value' });
});
We are using jqote2 with backbone because it's faster than jQuery's, as you say there are many :)
We have all our templates in a single tpl file, we bind to our template_rendered so we can add jquery events etc etc
App.Helpers.Templates = function() {
var loaded = false;
var templates = {};
function embed(template_id, parameters) {
return $.jqote(templates[template_id], parameters);
}
function render(template_id, element, parameters) {
var render_template = function(e) {
var r = embed(template_id, parameters);
$(element).html(r);
$(element).trigger("template_rendered");
$(document).unbind(e);
};
if (loaded) {
render_template();
} else {
$(document).bind("templates_ready", render_template);
}
}
function load_templates() {
$.get('/javascripts/backbone/views/templates/templates.tpl', function(doc) {
var tpls = $(doc).filter('script');
tpls.each(function() {
templates[this.id] = $.jqotec(this);
});
loaded = true;
$(document).trigger("templates_ready");
});
}
load_templates();
return {
render: render,
embed: embed
};
}();
They look like
<script id="table" data-comment="generated!!!!! to change please change table.tpl">
<![CDATA[
]]>
</script>

Categories

Resources