I am writing code to detect breakpoints via js using match media. In plain js, I know how to create a separate utility for this and consume it, but in Ember, how do I go about it, would I need to create a helper or something else.
Plain JS code:
define('viewportDimension', function() {
var viewportSize ={
mqMaxTablet : '959px',
isTablet: function(){
if(matchMedia){
var mq = window.matchMedia("(max-width:" + this.mqMaxTablet+ ")");
mq.addListener(this.viewportChanged);
this.viewportChanged(mq);
}
},
viewportChanged: function(mq){
if(mq.matches){
return true;
}
}
};
return viewportSize;
});
Ember Controller:
isTablet: function (){
viewportDimension.isTablet();
}.property('')
I understand the above code will not work. I dont know how to make it more Ember'ish type. The "isTablet" property should be set to true, as soon as the media query match is done.
Started converting my plain js to emberish (as below), but dont know how to proceed.
define('viewportDimension',function(){
var viewportSize = Ember.Object.extend({
isTablet: function(){
alert("1");
}.property('')
});
return viewportSize;
});
Ember.Application.initializer({
name: 'viewport-dimension',
initialize: function(container,app){
require('viewportDimension',function(object){
app.ViewportDimension = object
})
}
})
Please take a look at simple-breakpoint-detector
Related
This javascript present on all site pages.
var CategoriesView = Backbone.View.extend({
el: $('.js-categories-view'),
initialize: function () {
...
}
...
templates: {
'category-template': _.template($('#js-category-template').html())
},
});
And if page haven't element $('.js-categories-view'), code like: new CategoriesView(); it will not be called and initialize not be called too.
But what about templates section?
_.template($('#js-category-template').html()) always called and I get the error:
Uncaught TypeError: Cannot read property 'length' of undefined
Because $('#js-category-template') doesn't present on page and and I don't want store template html on page where this View not needed?
You can check if the needed element present on the current page like this:
if( $('.js-categories-view').length ){
new CategoriesView();
}
And if you want to prevent error when calling the _.template() function, you also need to move the definition of the templates object into the initialize method of the view like follows:
var CategoriesView = Backbone.View.extend({
el: $('.js-categories-view'),
initialize: function () {
this.templates = {
'category-template': _.template($('#js-category-template').html())
};
...
}
});
Thanks all! It's good solution. But eventually I implement this:
$(function () {
if (!$('.js-categories-view').length) {
return;
}
var CategoriesPageModel = Backbone.Model.extend({
...
to not to think about issues like this. But I think thant better solution can be found
I read and tried a lots of solution but i wasn't able to force the Template.dynamic to render again.
In html >>
<body>
{{> Template.dynamic template=Template}}
</body>
In Meteor.isClient >>
Template.body.helpers({
'Template': function() {
return page.template;
}
});
I have a function on hashchange event which will change the value of page.template, the event works fine and value will changed every time, but i can't force the Template.dynamic to render again.
page.template is string
I have a function page.getTemplate() > return page.template just to try all options
I'm using the last version of Meteor 1.1.0.2
I am not sure how your app is organized but this should be an easy task. Just use a ReactiveVar to save your active template-name you wish to have selected.
I made a simple MeteorPad for you. Hopefully this is what you are looking for.
http://meteorpad.com/pad/oPhK4KqjiSztRSa9K/SimpleDynamicTemplateSwitch
Cheers
Tom
Before start , i changed some objects , page.template is now object and page.template.get() will return string, but i don't use it, i pass the template name in Sessions, and this is my page.template.set()
page.template.set = function(name) {
Session.set('template', name);
};
Well i found the answer, you need to set a dependency to Sessions, i have done this so far
Template.body.helpers({
'Template': function() {
return Session.get('template');
}
});
Edited
Because of client hack i decided to changed something (you can change the session in console, and i want my router decide to which template should be shown)
page.template.set = function(name) {
page.template.name = name;
Session.set('template', name);
};
page.template.get = function() {
return page.template.name;
};
Template.body.helpers({
'Template': function() {
return Session.get('template') ? page.template.get() : page.template.get();
}
});
I am trying to dynamically get and set a pageTitle for my sample Meteor app, ideally I'd like to use jQuery, but any other solution would be good too.
I am trying to do it the rough way by setting a session when a certain div class exists on the page, but it's not working for some reason.
Basically, I have this:
Template.layout.helpers({
pageTitle: function() { return Session.get('pageTitle'); }
});
And I want to do something like
if ($('section').hasClass('single')) {
Session.set('pageTitle', 'Post Page');
}
Any idea ho to make this work? thanks!
You need to call it in a controller or the templates rendered section like this:
Template.layout.helpers({
pageTitle: function() {
return Session.get('pageTitle');
}
});
// set when a page template renders
Template.posts.rendered = function() {
setPageTitle("Blog Posts");
};
// or with Iron Router on *every* route using some sort of variable
Router.onBeforeAction(function() {
var someDynamicValue = "FOO";
setPageTitle(someDynamicValue);
});
// or in an IronRouter Controller
PostsController = RouteController.extend({
onBeforeAction: function() {
setPageTitle("Blog Posts");
}
});
// helper function to set page title. puts a prefix in front of page, you
// could opt set a boolean to override that
function setPageTitle(titleName) {
var prefix = "My Site - ";
if ($('section').hasClass('single')) {
Session.set('pageTitle', prefix + titleName);
}
}
As #Kuba Wyrobek pointed out, I needed to use the Template.layout.rendered function.
Here's a snippet that works
Template.postsList.rendered = function(){
Session.set('pageTitle', 'Listing Page')
};
i have some links in a web page ,what i want to do :
Trigger click event on every link
When the page of every link is loaded , do something with page's DOM(fillProducts here)
What i have tried :
function start(){
$('.category a').each(function(i){
$.when($(this).trigger('click')).done(function() {
fillProducts() ;
});
})
}
Thanks
What you want to do is much more complicated than you seem to be giving it credit for. If you could scrape webpages, including AJAX content, in 7 lines of js in the console of a web browser you'd put Google out of business.
I'm guessing at what you want a bit, but I think you want to look at using a headless browser, e.g. PhantomJs. You'll then be able to scrape the target pages and write the results to a JSON file (other formats exist) and use that to fillProducts - whatever that does.
Also, are you stealing data from someone else's website? Cause that isn't cool.
Here's a solution that may work for you if they are sending their ajax requests using jQuery. If they aren't you're going to need to get devilishly hacky to accomplish what you're asking (eg overriding the XMLHttpRequest object and creating a global observer queue for ajax requests). As you haven't specified how they're sending the ajax request I hope this approach works for you.
$.ajaxSetup({
complete: function(jQXHR) {
if(interested)
//do your work
}
});
The code below will click a link, wait for the ajax request to be sent and be completed, run you fillProducts function and then click the next link. Adapting it to run all the clicks wouldn't be difficult
function start(){
var links = $('.category a');
var i = 0;
var done = function() {
$.ajaxSetup({
complete: $.noop//remove your handler
});
}
var clickNext = function() {
$(links.get(i++)).click();//click current link then increment i
}
$.ajaxSetup({
complete: function(jQXHR) {
if(i < links.length) {
fillProducts();
clickNext();
} else {
done();
}
}
});
clickNext();
}
If this doesn't work for you try hooking into the other jqXHR events before hacking up the site too much.
Edit here's a more reliable method in case they override the complete setting
(function() {
var $ajax = $.ajax;
var $observer = $({});
//observer pattern from addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjquery
var obs = window.ajaxObserver = {
subscribe: function() {
$observer.on.apply($observer, arguments);
},
unsubscribe: function() {
$observer.off.apply($observer, arguments);
},
once: function() {
$observer.one.apply($observer, arguments);
},
publish: function() {
$observer.trigger.apply($observer, arguments);
}
};
$.ajax = function() {
var $promise = $ajax.apply(null, arguments);
obs.publish("start", $promise);
return $promise;
};
})();
Now you can hook into $.ajax calls via
ajaxObserver.on("start", function($xhr) {//whenever a $.ajax call is started
$xhr.done(function(data) {
//do stuff
})
});
So you can adapt the other snippet like
function start(){
var links = $('.category a');
var i = 0;
var clickNextLink = function() {
ajaxObserver.one("start", function($xhr) {
$xhr.done(function(data) {
if(i < links.length) {
fillProducts();
clickNextLink();
} else {
done();
}
});
})
$(links.get(i++)).click();//click current link then increment i
}
clickNextLink();
}
try this:
function start(){
$('.category a').each(function(i){
$(this).click();
fillProducts() ;
})
}
I get ya now. This is like say:
when facebook loads, I want to remove the adverts by targeting specific class, and then alter the view that i actually see.
https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/
Is a plugin for firefox, this will allow you to create a javascript file, will then allow you to target a specific element or elements within the html rendered content.
IN order to catch the ajax request traffic, you just need to catcher that within your console.
I can not give you a tutorial on greasemonkey, but you can get the greasemonkey script for facebook, and use that as a guide.
http://mashable.com/2008/12/25/facebook-greasemonkey-scripts/
hope this is it
I have already implemented some AJAX pagination in my Rails app by using the example code for the will_paginate plugin--which is apparently using Prototype.
But if I wanted to switch to using jQuery for future additions, I really don't want to have the Prototype stuff sitting around too (yes, I know it's possible). I haven't written a lick of JavaScript in years, let alone looked into Prototype and jQuery... so I could use some help converting this bit into jQuery-compatible syntax:
document.observe("dom:loaded", function() {
// the element in which we will observe all clicks and capture
// ones originating from pagination links
var container = $(document.body)
if (container) {
var img = new Image
img.src = '/images/spinner.gif'
function createSpinner() {
return new Element('img', { src: img.src, 'class': 'spinner' })
}
container.observe('click', function(e) {
var el = e.element()
if (el.match('.pagination a')) {
el.up('.pagination').insert(createSpinner())
new Ajax.Request(el.href, { method: 'get' })
e.stop()
}
})
}
})
Thanks in advance!
Edit: Nick Craver's answer got me 90% of the way there, so I just had to pick up enough jQuery to make the HTML element substitution. In place of the line where Nick had $.get($(this).attr("href"));, put this line:
$.get(this.href, null, function(data){ $(this).html(data); }, 'html');
You can shorten this down a bit in jQuery to:
$(function() {
$('.pagination a').live('click', function(e) {
$(this).parent('.pagination')
.append("<img src='/images/spinner.gif' class='spinner' />");
$.get($(this).attr("href"));
return false;
});
});
I'm not entirely sure about new Ajax.Request(el.href, { method: 'get' }) though, is this a script being requested? It looks like nothing's being done with the content after return.