Giter Site home page Giter Site logo

meteor-mini-pages's Introduction

Check out the new iron-router project!

https://github.com/eventedmind/meteor-iron-router

mini-pages

mini-pages is a simple client side page routing library for Meteor.

Latest Version: 0.3.1

Previous Version: 0.3.0

API Docs

Install

To install in a new project:

> mrt add mini-pages

To update an existing project:

> mrt update mini-pages

Run the Example

> git clone https://github.com/cmather/meteor-mini-pages.git mini-pages
> cd mini-pages/examples/basic
> mrt

Run Tests

> git clone https://github.com/cmather/meteor-mini-pages.git mini-pages
> mrt

Quick Start

<body>
  <!-- Nothing needed in body unless router autoRender is false and you manually use renderPages helper --->
</body>

<template name="layout">
  {{{yield}}}
</template>

<template name="postIndex">
</template>

<template name="postShow">
</template>

<template name="secret">
</template>

<template name="notFound">
</template>

Defining Routes

if (Meteor.isClient) {
  Meteor.pages({

    // Page values can be an object of options, a function or a template name string

    '/': { to: 'postIndex', as: 'root', nav: 'posts' },
    '/posts': { to: 'postIndex', nav: 'posts' },
    '/posts/:_id': { to: 'postShow', before: [setPost] },
    '/secret': { to: 'secret', nav: 'secret', before: secret },
    '/logout': logout,
    '*': 'notFound'
  }, {

    // optional options to pass to the PageRouter

    defaults: {
      layout: 'layout'
    }
  });
}

Before Callbacks

Before callbacks let you set page variables, and dynamically change the page's layout, nav key or template. Before callbacks are reactive. This means that if they rely on a reactive data source and that data changes, the callbacks will be run again.

function loggingIn () {
  if (Meteor.loggingIn()) {
    // dynamically set the template
    this.template("loggingIn");
    
    // stop downstream callbacks from running
    this.done();
  }
}

function first () {
  // set page specific variables using the set method
  this.set("post", { _id: 1 });
}

function second () {
  // dynamically set layout and nav keys or redirect
  this.layout("somelayoutTemplateName");
  this.nav("someNavKey");

  // redirect to a different path
  this.redirect(Meteor.someOtherPath());
}

Meteor.pages({
  '/posts/:_id': { to: "postShow", before: [loggingIn, first, second] }
});

Handlebars Helpers

  • {{renderPages}}: Manually render the pages. Must be used in combination with the autoRender: false option to the router.
  • {{pageTemplate}}: The current template name.
  • {{pageTemplateEquals 'value'}}: True if the value is equal to the current template.
  • {{pageNav}}: The current nav key.
  • {{pageNavEquals 'value'}}: True if the value is equal to the current nav key.
  • {{pageLayout}}: The current layout template name.
  • {{pageLayoutEquals 'value'}}: True if the value is equal to the current layout template name.
  • {{pagePath}}: The current path.
  • {{page}}: The current page's invocation dictionary. Access variabes that were set in before callbacks using the this.set("key", "value") method.

meteor-mini-pages's People

Contributors

belisarius222 avatar cmather avatar ianserlin avatar pokka avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

meteor-mini-pages's Issues

Html5 History-5 support breaks accounts token

Not sure if this is a problem of mini pages or not but the HTML5 history package used in conjunction with mini pages to support older browsers breaks the accounts package token's that get set by meteor on password reset and new enrollment. The token is always null in browsers that uses the history api because the of the way the match is written.

match = window.location.hash.match(/^#/reset-password/(.*)$/);

The hashtag has to be present to prevent security problems, what can we do ?

loggingIn Timing Issue

@belisarius222 brought up an issue in meteor-talk about timing. This probably requires some a good example since it should come up often.

Basic flow:

  1. Visit page
  2. auth token is present but login process has not started yet
  3. logged out page is temporarily shown
  4. login process begins behind the scenes
  5. logging in template shows
  6. login process completes
  7. after login page shows

The constant template changing would be jarring. Chris to investigate.

url changes breaking constant regions and preserves

Right now, the render function swaps out the whole document.body and replaces it with the layoutTemplate. This makes even constant regions inside the layoutTemplate get clobbered when the page changes. This is currently preventing my app from being able to launch an iframe for a user to invite friends through facebook using facebook's javascript SDK (which was working fine with the meteor-router package).

I understand that the machinery in mini-pages looks for the "yield" helper in the layout template. This might be better as a global Handlebars helper (maybe rename it to "currentPage" like the meteor-router), to remove the dependency on having a layoutTemplate.

Thanks!

The package named mini-pages does not exist.

I cloned the git repo and started up meteor. No joy.

$ mt
[[[[[ ~/Dev/meteor/mini-pages/examples/basic ]]]]]

No dependency info in bundle. Filesystem monitoring disabled.
=> Errors prevented startup:
Exception while bundling application:
Error: The package named mini-pages does not exist.
    at _.extend.initFromPackageDir (/home/aks/.meteor/tools/275efdf2db/tools/pac
kages.js:155:13)
    at _.extend.initFromWarehouse (/home/aks/.meteor/tools/275efdf2db/tools/pack
ages.js:197:10)
    at Object._.extend.get (/home/aks/.meteor/tools/275efdf2db/tools/packages.js
:347:15)
    at self.api.use (/home/aks/.meteor/tools/275efdf2db/tools/bundler.js:111:28)
    at Array.forEach (native)
    at Function._.each._.forEach (/home/aks/node_modules/underscore/underscore.j
s:78:11)
    at Object.self.api.use (/home/aks/.meteor/tools/275efdf2db/tools/bundler.js:
110:9)
    at _.extend.init_from_app_dir [as on_use_handler] (/home/aks/.meteor/tools/2
75efdf2db/tools/packages.js:238:11)
    at _.extend.use (/home/aks/.meteor/tools/275efdf2db/tools/bundler.js:450:11)
    at Object.exports.bundle (/home/aks/.meteor/tools/275efdf2db/tools/bundler.j
s:859:12)
    at /home/aks/.meteor/tools/275efdf2db/tools/run.js:694:26
    at exports.inFiber (/home/aks/.meteor/tools/275efdf2db/tools/fiber-helpers.j
s:24:12)

Please fix the problem and restart.

Okay... let's see what packages are included:

$ mt list --using
autopublish
insecure
preserve-inputs
mini-pages
bootstrap

okay.. let's see if we need to update:

$ mt update 
This project is already at Meteor 0.6.2.1, the latest release.

Finally, let's see what packages are known to meteor:

$ mt list

accounts-base           A user account system
accounts-facebook       Login service for Facebook accounts
accounts-github         Login service for Github accounts
accounts-google         Login service for Google accounts
accounts-meetup         Login service for Meetup accounts
accounts-password       Password support for accounts.
accounts-twitter        Login service for Twitter accounts
accounts-ui             Simple templates to add login widgets to an app.
accounts-ui-unstyled    Unstyled version of login widgets
accounts-weibo          Login service for Sina Weibo accounts
amplify                 API for Persistant Storage, PubSub and Request
appcache                enable the application cache in the browser
autopublish             Automatically publish the entire database to all clients
backbone                A minimalist client-side MVC framework
bootstrap               Front-end framework from Twitter
code-prettify           Syntax highlighting of code, from Google
coffeescript            Javascript dialect with fewer braces and semicolons
d3                      Library for manipulating documents based on data.
ejson                   Extended and Extensable JSON library
email                   Send email messages
force-ssl               Require this application to use secure transport (HTTPS)
handlebars              Simple semantic templating language
htmljs                  Easy macros for generating DOM elements in Javascript
http                    Make HTTP calls to remote servers
insecure                Allow all database writes by default
jquery                  Manipulate the DOM using CSS selectors
jquery-history          pushState module from the jQuery project
jquery-layout           Easily create arbitrary multicolumn layouts
jquery-waypoints        Execute a function when the user scrolls past an element
less                    The dynamic stylesheet language.
localstorage-polyfill   Simulates the localStorage API on IE 6,7 using userData
madewith                Made With Meteor badge
preserve-inputs         Automatically preserve all form fields with a unique id
showdown                Markdown-to-HTML processor
spiderable              Makes the application crawlable to web spiders.
stylus                  Expressive, dynamic, robust CSS.
underscore              Collection of small helper functions: _.map, _.each, ...

Inner Layouts and routes

Is it possible to use this meteorite package to achieve the following example.

Let's say i have two routes "/home" & "/home/teaching"; When the former route is 'hit', the following template gets displayed.

<template name="home"> 

 <div inner-content>
     {{> Inner Home}}
 </div>
</template> 

Notice how i have an inner template which is described below.

I would like to (if this is possible), display the 'home_teaching' template within my 'Inner Home' template.

So, if i have the route 'home/teaching', bound to the template name 'home_teaching', i want it to render inside of the the 'inner_home' template and not have to use sessions to replace pieces of information. I know this package deals with layouts but does it deal with inherited and multi-layered layouts?

Can add routes only once

Routes can only be defined once using Meteor.pages();. Every successive call triggers an error. For modular applications there should be a way to define routes at multiple locations (each module their own routes).
Right now I'm having a common module where I do create all routes at once (with every other module having a dependency on this common module). However as this module is loaded first, warnings are thrown for missing templates.

Path helper when using nested documents.

First of all, thanks for a great contribution to Meteor. It saved me a lot of time.

Just a thought on an improvement.

I'd like to be able to use the path helper to create paths based on multiple documents ids. For example, with two collections, books and chapters, and documents looking like this:

book = {
    _id: "123"
}

chapter = {
    _id: "456",
    book: 123
}

I'd like to use paths like this:

'/books': { to: "bookIndex" },
'/book/:book_id': { to: "viewBook" },
'/book/:book_id/chapter/:chapter_id': { to: "viewChapter" },

If I have a template helper that returns the chapters for the selected book I'd like to use the template code like this:

<template name="bookIndex">
{{#each book}}
    <a href="{{ viewBookPath }}">link</a>
{{/each}}
</template>

<template name="viewBook">
{{#each chapters }}
    <a href="{{ viewChapterPath }}">link</a>
{{/each}}
</template>

Right now I use "before" when routing to "viewBook" and set a Session key with the current book, then in the viewBook template I use a handlebars helper to get the Session value and use it in the href:

{{#each chapters }}
    <a href="/book/{{ session 'book_id' }}/chapter/{{ _id }}">link</a>
{{/each}}

It works, but hardcoding the path is suboptimal, and if you have deeper nesting than two levels you need a lot of "before" functions and Session variables to keep up with the location.

Ideally this should also work if you use subdocuments instead of related documents (but then you'd have to manually set some unique identifier on the subdocuments since they do not get that by default).

per-page reactive data source

For tracking purposes, I thought I'd add this issue from our previous conversation:

"A page should really have its own reactive data source (like Session) that goes away when the page isn't loaded."

This would be really fantastic - I wouldn't have to name my session variables things like userVideosShowIconClass in order to avoid name collisions.

Problem with navClassFor

I have the normal {{navClassFor}}, like this:

<li class='dropdown' class="{{navClassFor 'users'}}">

and my helper is set up like this:

Handlebars.registerHelper('navClassFor', function(nav, options) {
  path = Meteor.router.path().split('/')[1];
  if(Meteor.router.navEquals(nav) || path === nav) {
    return 'active';
  } else {
    return '';
  }
});

So, theoretically, if someone goes to mydomain/users/123 or mydomain/users/123/settings, the <li> should receive the active class. However this doesn't happen. I've determined that path does indeed match nav when it's supposed to but the <li> just never gets the class.

Anybody else have this issue?

document how to find the current route

Hey Chris, thanks for creating this project. I'm trying it out as a possible replacement for meteor-router. Something I think you should add to the README is how to find the current route. It looks like it would be: Meteor.router.current().as.

Trying to make a package with mini-pages

I'm trying to do a package with mini-pages but it always raises an error saying that Meteor.router is undefined.
To reproduce, clone those two repos to the same folder:
https://github.com/gabrielhpugliese/mini-pages-package
https://github.com/gabrielhpugliese/test-mini-pages-package

And then mrt run into test-mini-pages-package folder.
Maybe I'm missing something (I'm probably doing something wrong):

package.js:

Package.describe({
  summary: "mini-pages test"
});

Package.on_use(function (api) {
  api.use(['templating','mini-pages'], 'client');
  api.add_files(['test-mini-pages.html','test-mini-pages.html'], 'client');
  api.add_files(['test-mini-pages.js'], ['client','server']);
});

test-mini-pages-package.js:

if (Meteor.isClient) {
  Template.hello.greeting = function () {
    return Meteor.router.path();
  };
{...}
}

mini-pages reloads entire page for anchor tag links, but not with Meteor.go()

In my app using mini-pages, the entire page reloads on a route triggered by anchor link, but if I call the same route with Meteor.go(route), it doesn't.

In an earlier version of the app, it works fine, but I don't believe I've touched the mini-pages config since then. Any idea why this would be happening?

Diff Mini-Pages vs Router

Your readme is not clear about the benefits to use meteor-router vs mini-pages.

Could you provide some details about differences.

Thank you

Reactiveness inside a Deps.autorun

Hi,

I'm trying to add a class to a li within a bootstrap nav-list when I'm in the current li path. I'd like to do it inside an Deps.autorun context, but Meteor.router is not loaded when that context is run. Let me example it:

Deps.autorun(function () {
    if (!Meteor.router)
        return;

    var active = _.find($('.nav-list li a'), function (item) {
        return $(item).attr('href') === Meteor.router.path();
    });
    $('.nav-list li').removeClass('active');
    $(active).parent().addClass('active');
});

This simply not run because it enters in the first if statement. If I remove it, Meteor.router is undefined and an Error is raised.
I expected Meteor.router to be reactive so that context would re-run.

Am I doing anything wrong ?
Thanks

Found your video on client side routing intriguing

@cmather how is this project currently looking? Are there any feature requests (from you or from others) on mini-pages?

I am looking to increase my opensource/github presence and meteor has been my most recently found love. Most recently, I have spent time working on meteor-sharejs fork implementing meteor users integration with sharejs, currently deployed here.

I am watching eventedmind videos and reading discovering meteor by Coleman and Grief to get up to speed with meteor and any real life experience implementing something related and getting it critiqued would be awesome. So thanks!

Remembering Last Attempted Path

Coming from Django and how the routing system worked over there, if the user attempted to visit a restricted path '/home/secret' an 'Authentication' filter is put in place to route the user back to the login page. Once the user successfully logs in, there routed immediately to the last path in this case the path they tried to visit before being authenticated if that makes sense.

There might be a way to do this with the current API and i am just looking for a nudge forward and some ideas on how to accomplish this.
Thanks

Support transparent template rendering in before callbacks

[ from google-talk discussion thread ]

Thanks for the package and videos!

I am trying out mini-pages and wanted to ask if there was a way to accomplish a 'behind the scenes' template dispatch without doing a context.redirect / changing the URL? This is the default behavior in meteor-router and I've found it very user-friendly in certain situations.

For example, an 'authenticate' before filter could transparently render a 'loading' template when Meteor.loggingIn() is true or render a 'signin' template when '! Meteor.user()'. Then, since the before filters are reactive, once that state changes, they automatically fulfill the initial request.

pathWithContext is broken with optional parameters.

Meteor.pages({
'/:param1?/:param2?/:param3?': { to: 'template' }
})

Meteor.templatePath({param1: 'test', param2: 'moo'}) returns "/?/?/?", due to the way pathWithContext only replaces the ':' and then searches for the exact key.

Try to circumvent this with Meteor.templatePath({'param1?': 'test', 'param2?': 'moo'}) and it returns "/test?/moo?/?"

So the issues:

  • The question mark needs to be in the key search
  • The question mark isn't removed
  • Non-required parameters are returned as question marks

Unfortunately I don't have time to fix this atm and so am just using a work-around of defining paths. Ideally I would add extra validation after "prop = part.replace..." to do a match on question mark. If it exists and not in context, path replace including the slash. Or something.

Presumably this will also affect regex defined arguments, but I haven't tested that, so can't say for sure!

Sorry I don't have time to work something more out, this is a great package! Thank you!

Feedback from @fritz-gerneth

  1. Handling multiple navigations within the nav-key. I'm storing an object there with key being the navigation and key the page-name. A custom helper takes the name of the navigation and the page to decide if the page is active (similar to your navClassFor helper)
    Callbacks when matching routes.
  2. Sometimes I want routes only to match when a callback returns true and fall through else (possibly matching another route), I could use the before callbacks, sure. However these have to know the the else-branch as well and don't allow other routes to match instead.

handle ctrl/cmd + click on links

Hi there!

As I have filed an issue to the original meteor-router package, this affects mini-pages as well: currently clicking links (that lead to a known routes) with ctrl/cmd down doesnt open a new tab as expected, how could i restore that behavior?

Thanks!

Greedy layout replacing existing body contents

The layout is rendered into the body replacing all previous content.
Besides making it hard to use other stuff there as well it makes testing using TinyTest impossible (the test-results are replaced by the template)
Suggesting an (optional?) helper like in version 0.1.5.

Access to url fragments

If I have a route like:

Meteor.pages({
  '/:something' : { to: 'someplace' }
});

How do I get access to the :something bit inside of my templates?

problem with context.redirect?

I upgraded to 0.2.1 last night, and most things work fine but occasionally my app goes completely haywire. I'm not sure this is the only problem but I have a reproducible issue. The relevant parts of my config looks like this:

showUserDashboard = (context) ->
  if Meteor.userId()
    context.redirect Meteor.userDashboardPath()

authorizeUser = (context) ->
  unless Meteor.userId()
    context.redirect Meteor.signinPath()

Meteor.pages
  '/'               : to: 'index',          before: showUserDashboard
  '/signin'         : to: 'signin'
  '/user/dashboard' : to: 'userDashboard',  before: authorizeUser, layout: 'userNavLayout', nav: 'dashboard'
  '*'               : to: 'notFound',       layout: 'errorLayout'

If I sign in and sign out everything works fine. However, the moment I get showUserDashboard involved, everything goes to hell. Specifically:

Scenario 1

  1. sign in: (looking at userDashboard)
  2. sign out: (looking at index)
  3. attempt to go to '/user/dashboard': (redirected to signin page)

After (3), the app acts like it doesn't have access to my template event code anymore. When I do something like submit a form the events don't get fired.

Scenario 2

  1. sign in: (looking at userDashboard)
  2. attempt to go to '/'

After (2) the page doesn't even render right, and again it's as if the template code is missing. I have to manually call Meteor.logout() and refresh the page in order to get out. Wild.

Solutions

  1. Let me know if you have any suggestions off the top of your head after reading this.
  2. I can try and distill the problem down to a simple demo (though that may take some time).
  3. I can grant you permissions to my private repo so you can try it yourself.

It's totally possible this is either me getting it wrong (though I was pretty careful in upgrading), or this is an interaction issue with some other package I'm using (specifically jade-handlebars).

suggestions for non-id-based routes?

If I have a route that looks like:

'user/videos/:_id/edit': {to: 'userVideosEdit'}

This is easy to use in a template:

{{#each videos}}
  <a href="{{userVideosEditPath}}">my video</a>
{{/each}}

because each video has an _id property. What if I wanted to change the route to look for a parameter called videoId instead?

'user/videos/:videoId/edit': {to: 'userVideosEdit'}

How could I make this work with my template? Passing an object literal doesn't seem to work, e.g.:

{{#each videos}}
  <a href="{{userVideosEditPath {videoId: this._id}}}">my video</a>
{{/each}}

i18n with mini-pages

Hi. Is it possible to build i18n(multi language) web sites with mini-pages and Meteor?
If yes, where can we find tutorials/examples?

Thanks.

0.6.5 breaks mini-pages?

I get the following error in the browser console:

Uncaught Error: Your template engine might not be supported in the mini-pages package. Could not find PageRouter.onAttachPathHelper which is normally defined in the mini-pages/lib/helpers.js file

redirect in a before filter

Is it possible to make before filters modify the URL? I have something that looks like this:

showUserDashboard = (context) ->
  if Meteor.userId()
    context.stop()
    Meteor.go Meteor.pages.userDashboardPage()

Meteor.pages
  '/': { to: 'index', before: showUserDashboard }

So then the user requests '/', she will be shown her dashboard if she is already logged in. It would be nice if Meteor.go could actually modify the URL in this case.

Yield content breaks existing container style

I'm using Foundation.

Original code:

<div class="row">
   {{template name}}
</div>

Behavior: template contents is put on page with left and right margins

New code:

<div class="row">
   {{yield}}
</div>

Behavior: template contents is put on page without left and right margins

Difficulty finding 'nav' session variable in new release

The screencast for the previous version illustrated an example for switching navbar classes based on the router 'nav' value:

Handlebars.registerHelper('navClassFor', function (nav, options) {
  return Session.equals('nav', nav) ? 'active' : ''
});

Latest release breaks this example. Looking through the code, I noticed that the 'nav' variable is now referred to differently:

var sessionNavKey = "mini-pages-router_nav";

I can certainly fix the problem by renaming 'nav' to 'mini-pages-router_nav' in my code, but is this the intended use, or is there now a different/better way to go about things?

Thanks!

Could not locate package.js

I'm trying to install the mini-pages package using mrt. I'm not sure on what to do, mrt installs other packages (ie bootstrap) without a problem. When I run the mrt add mini-pages I get the following :

Tesla:wtf_app Username$ mrt add mini-pages
smart.json changed.. installing from smart.json
โœ“ mini-pages
    tag: https://github.com/cmather/meteor-mini-pages.git#v0.3.1

/usr/local/lib/node_modules/meteorite/lib/dependencies/package.js:106
      throw('Could not locate package.js within path ' + self.source.packagePa
                                                       ^
Could not locate package.js within path /Users/Username/.meteorite/packages/mini-pages/cmather/meteor-mini-pages/d218140d37b0dbec975880755c2035ae9e022936
Tesla:wtf_app Username$ 

I'm working on:
osX10.8
node 0.10.10
meteor 0.6.4
mrt 0.6.1

Inner Layouts and routes

Is it possible to use this meteorite package to achieve the following example.

Let's say i have two routes "/home" & "/home/teaching"; When the former route is 'hit', the following template gets displayed.

<template name="home>

{{> Inner Home}}

Notice how i have an inner template which is described below.

I would like to (if this is possible), display the 'home_teaching' template within my 'Inner Home' template.

So, if i have the route 'home/teaching', bound to the template name 'home_teaching', i want it to render inside of the the 'inner_home' template and not have to use sessions to replace pieces of information. I know this package deals with layouts but does it deal with inherited and multi-layered layouts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.