I'm doing the application, the use of backbone.js and require.js, I would like to achieve dynamic configuration module navigation by the "backbone.router" function, here is my question?
This is my baserouter defined,I want to achieve dynamic load "backbone.view" according to "the viewPath" parameter.How can I do?
define(['require', 'underscore', 'backbone'], function(require, _, Backbone) {
var BaseRouter = Backbone.Router.extend({
container: "#page",
loadView: function(viewPath) {
**//Here require lazy loading "base/people/view.js", **
**//I do not know how to achieve it?**
var view = require(viewPath);//viewPath = "base/people/view";
this._currentView = new view();
this._currentView.render();
$(this.container).html(this._currentView.el);
}
});
return BaseRouter;
});
This is the definition of the router, it work with "baserouter" to dynamically set the navigation menu.
define(['baserouter'], function(baserouter) {
//The JSON data should come from the database,
//These data define the navigation information for all modules.
var navs = JSON.parse('[{"name": "people","title": "peoplemanage","view": "base/people/view"},{"name": "test","title": "testmanage","view": "pub/test/view"}]');
var AppRouter = baserouter.extend();
for (var i = 0, l = navs.length; i < l; i++) {
var nav = navs[i];
AppRouter.prototype["loadView_" + nav.name] = function() {
var path = nav.view;
return function() {
AppRouter.prototype.loadView(path);
}
}();
}
var initialize = function() {
var routes = {}
for (var i = 0, l = navs.length; i < l; i++) {
var nav = navs[i];
routes[nav.name] = "loadView_" + nav.name;
}
var app_router = new AppRouter({
"routes": routes
});
Backbone.history.start();
};
return {
initialize: initialize
};
});
Here is the html code for the navigation menu:
<ul class="dropdown-menu">
<li>people</li>
<li>test</li>
</ul>
This method can achieve.But I'm not sure this is the best practice, and who has a better way?
loadView: function(viewPath) {
var _this = this;
if (this._currentView) {
this._currentView.dispose();
}
//var view = require(viewPath);
//**This method can achieve.But I'm not sure this is the best practice, and who has a better way?**
//setTimeout(function() {
require([viewPath], function(view) {
_this._currentView = new view();
_this._currentView.render();
$("#page").html(_this._currentView.el);
});
//}, 100);
Related
I want to override "_render: function ()" function from pivot_renderer.js file in web but not working in custom module. Here is the code i am implementing in my custom module:-
odoo.define('MY_CUSTOM_MODULE_NAME.renderer', function (require) {
"use strict";
var PivotRenderer = require('web.PivotRenderer');
var field_utils = require('web.field_utils');
var core = require('web.core');
var _t = core._t;
PivotRenderer.include({
init: function(parent, state, params) {
this._super.apply(this, arguments);
},
_render: function () {
if (!this._hasContent()) {
// display the nocontent helper
this.replaceElement(QWeb.render('PivotView.nodata'));
return this._super.apply(this, arguments);
}
if (!this.$el.is('table')) {
// coming from the no content helper, so the root element has to be
// re-rendered before rendering and appending its content
this.renderElement();
}
var $fragment = $(document.createDocumentFragment());
var $table = $('<table>').appendTo($fragment);
var $thead = $('<thead>').appendTo($table).addClass("CLASS_NAME");
var $tbody = $('<tbody>').appendTo($table);
var nbr_measures = this.state.measures.length;
var nbrCols = (this.state.mainColWidth === 1) ?
nbr_measures :
(this.state.mainColWidth + 1) * nbr_measures;
for (var i=0; i < nbrCols + 1; i++) {
$table.prepend($('<col>'));
}
this._renderHeaders($thead, this.state.headers);
this._renderRows($tbody, this.state.rows);
// todo: make sure the next line does something
$table.find('.o_pivot_header_cell_opened,.o_pivot_header_cell_closed').tooltip();
this.$el.html($table.contents());
return this._super.apply(this, arguments);
},
});
});
In the above, i want to add a class in the header for calling my custom css "var $thead = $('').appendTo($table).addClass("CLASS_NAME");" with this syntax but it is not reflecting in my custom module. Although, for testing, I have implemented same class in default web module and it is working fine. The issue is in custom module.
So how to solve this issue? Is there any other way for calling class or i am doing it in a wrong way?
var $thead = $('').addClass("CLASS_NAME").appendTo($table);
This will work in my case. You can try it.
Hi Im just a rookie with polymer, I hope this question doesnt sound stupid for you :(
I am triying to make a image gallery and I am using this idea: From this page
<dom-module id="simple-gallery" >
<script>
HTMLImports.whenReady(function () {
(function() {
var current_index = 0;
var image_length = 0;
Polymer({
is: "simple-gallery",
ready: function() {
var images = Polymer.dom(this).querySelectorAll('img');
var container = this.$.links;
for (var img in images) {
images[img].addEventListener('click',this.load_popup);
container.appendChild(images[img]);
}
},
load_popup: function(e, detail, sender) {
e.preventDefault();
var links = document.getElementById('links');
image_length = links.getElementsByTagName('img').length;
var image_url = e.target.getAttribute('data-original');
var modalbody = document.getElementsByClassName("modal-body")[0];
var modal_img = modalbody.getElementsByTagName('img')[0];
modal_img.setAttribute("src",image_url);
var modal = document.getElementsByClassName("modal")[0];
modal.style.display = 'block';
current_index = parseInt(e.target.getAttribute('data-index').replace("s",""));
return false;
},
next: function () {
current_index = current_index + 1;
if(current_index == (image_length + 1) ){
current_index = 1;
}
var current_image = document.querySelectorAll("[data-index='s"+current_index+"']");
image_url = current_image[0].getAttribute('data-original');
var modalbody = document.getElementsByClassName("modal-body")[0];
var modal_img = modalbody.getElementsByTagName('img')[0];
modal_img.setAttribute("src",image_url);
},
prev: function () {
current_index = current_index - 1;
if(current_index == 0 ){
current_index = image_length;
}
var current_image = document.querySelectorAll("[data-index='s"+current_index+"']");
image_url = current_image[0].getAttribute('data-original');
var modalbody = document.getElementsByClassName("modal-body")[0];
var modal_img = modalbody.getElementsByTagName('img')[0];
modal_img.setAttribute("src",image_url);
},
close: function () {
var modal = document.getElementsByClassName("modal")[0];
modal.style.display = "none";
},
});
})();
});
</script>
<template>
I realy dont understand why this code works fine if I use it as in the example, but if I create a proyect with: polymer init app-drawer-template and I use this as an element wich is called from one of the views I have an error :(
Uncaught ReferenceError: HTMLImports is not defined(anonymous function) # simple-gallery.html:91
Surely I am not understanding well something but I dont know why, hope somebody has the time to give me a brief explanation :(
thanks a lot for your time.
I had the same issue so I have added following include in my main html:
<script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script>
Which worked for me.
How can I create textfield or textarea with in rowbodytpl of extjs grid (rowexpander). Also my program needs to read these fields and update the DB. I would love to know the use of radiogroup within rowbodytpl
I guess the best way is to implement plugin which can render any component into rowbody. Then you can just pass any component config to it.
Example plugin:
Ext.define('Ext.ux.grid.SubCmp', {
extend: 'Ext.grid.plugin.RowExpander',
alias: 'plugin.subcmp',
rowBodyTpl: ['{%this.owner.renderComponent(out, values);%}'],
// override this method and return component config
componentConfigFn: function(record) { return {}; },
init: function(grid) {
var me = this,
store = grid.getStore(),
view = grid.getView();
me.components = {};
me.callParent(arguments);
// when grid is reloaded we should destroy all created components
grid.on('beforedestroy', me.destroyComponents, me);
store.on('beforeload', me.destroyComponents, me);
// renders component
view.on('expandbody', me.onExpandBody, me);
// modify getRefItems method of grid to allow querying components from rowbody
grid.getRefItems = (function() {
var originalFn = grid.getRefItems;
return function(deep) {
var result = originalFn.call(grid, deep);
if (deep) {
for (var i in me.components) {
result.push(me.components[i]);
result.push.apply(result, me.components[i].getRefItems(true));
}
}
return result;
}
}());
},
destroyComponents: function() {
var me = this,
components = me.components;
for (var i in components) {
components[i].destroy();
}
me.components = {};
},
onExpandBody: function(rowNode, record, expandRow, eOpts) {
var me = this,
grid = me.grid,
recordId = record.id,
componentWrapId = grid.id + '-component-wrap-' + recordId,
component = me.components[recordId];
if (component && !component.rendered) {
component.render(componentWrapId);
}
},
renderComponent: function (out, rowValues) {
var me = this,
grid = me.grid,
store = grid.getStore(),
recordId = rowValues.id,
record = store.getById(recordId),
componentWrapId = grid.id + '-component-wrap-' + recordId,
componentId = grid.id + '-component-' + recordId,
component,
config;
if (me.components[recordId]) {
return; // already rendered
}
config = Ext.apply({}, { id: componentId }, me.componentConfigFn(record));
me.components[recordId] = component = Ext.create(config);
out.push('<div id="' + componentWrapId + '"></div>');
}
});
To select components from rowbody, you can use grid.query method.
Fiddle: http://jsfiddle.net/znnqxmyq/9/
I learn typescript and angularjs for a few days,and now I have a question that confuses me for days, I want to make a gps tracking system, so I try to write a service like this:
1.
module Services {
export class MyService {
getGpsPeople(): Array<AppCommon.GPSPerson> {
var gpsPeople = new Array<AppCommon.GPSPerson>()
for (var i = 0; i < 10; i++) {
var tempPerson = new AppCommon.GPSPerson({ name: "username" + i.toString() });
gpsPeople.push(tempPerson);
}
return gpsPeople;
}
} // MyService class
}
A controller like this:
module AppCommon {
export class Controller {
scope: ng.IScope;
constructor($scope: ng.IScope) {
this.scope = $scope;
}
}
}
module Controllers {
export interface IMyScope extends ng.IScope {
gpsPeople: Array<AppCommon.GPSPerson>;
}
export class MyController extends AppCommon.Controller {
scope: IMyScope;
static $inject = ['$scope','myService'];
constructor($scope: IMyScope,service:Services.MyService) {
super($scope);
$scope.gpsPeople = service.getGpsPeople();
}
}
}
3.The GPSPerson class like this:
export class GPSPoint {
latitude = 0;
longtitude = 0;
constructor(la: number, lg: number) {
this.latitude = la;
this.longtitude = lg;
}
}
export interface IPerson {
name: string;
}
export class GPSPerson
{
name: string;
lastLocation: GPSPoint;
countFlag = 1;
historyLocations: Array<GPSPoint>;
timerToken: number;
startTracking() {
this.timerToken = setInterval(
() => {
var newGpsPoint = null;
var offside = Math.random();
if (this.countFlag % 2 == 0) {
newGpsPoint = new GPSPoint(this.lastLocation.latitude - offside, this.lastLocation.longtitude - offside);
}
else {
newGpsPoint = new GPSPoint(this.lastLocation.latitude + offside, this.lastLocation.longtitude + offside);
}
this.lastLocation = newGpsPoint;
this.historyLocations.push(newGpsPoint);
console.log(this.countFlag.toString() + "+++++++++++++++++++" + this.lastLocation.latitude.toString() + "----" + this.lastLocation.longtitude.toString());
this.countFlag++;
}
, 10000);
}
stopTracking() {
clearTimeout(this.timerToken);
}
constructor(data: IPerson) {
this.name = data.name;
this.lastLocation = new GPSPoint(123.2, 118.49);
this.historyLocations = new Array<GPSPoint>();
}
}
The problem is:
1.Should I make the GPSPerson class a Controller?
2.The setinterval works but the UI dose not change(when I hit button ,it changes,the button do nothing )?
I'm a beginner of ts and angular,and have no experience with js, I do not know if I have explained it clearly, hope someone can help me, thanks!
setInterval works but the ui dose not change
This is because the angular $digest loop does not run on completion of setInterval. You should use $interval service https://docs.angularjs.org/api/ng/service/$interval as that tells Angular to do its dirty checking again.
You just need to provide MyService access to $interval though. Inject it using $inject (see https://www.youtube.com/watch?v=Yis8m3BdnEM&hd=1).
1.should i make the GPSPerson class a Controller?
No. Its an array of JavaScript objects inside the controller and that is fine.
I would separate the tracking logic and keep just the data in GPSPerson. For the tracking logic I would make a factory.
My examples are not in Typescript but I'm sure you will have no problem in converting the code if you want.
This is a link to a Plunk
I've made a much simpler example but I think you'll understand the idea.
The factory would have two methods for start and stop tracking. They will take a person as parameter.
app.factory('tracking',function($interval){
var trackingInterval;
var trackingFn = function(person){
var currentPos = Math.floor(Math.random()*10);
var newPosition = {id:person.positions.length, position:currentPos};
person.positions.push(newPosition);
};
var startTracking = function(person){
person.interval = $interval(function(){
trackingFn(person);
},2000);
};
var stopTracking = function(person){
console.log('STOP');
$interval.cancel(person.interval);
};
var getNewTrack = function(){
};
return {
startTracking: startTracking,
stopTracking: stopTracking,
};
});
I've also made a very simple directive to show the data
app.directive('position',function(){
return {
templateUrl: 'positionTemplate.html',
link: function(scope, element,attrs){
}
}
});
and the template look like this
<div>
<button ng-click="startTracking(person)">Start tracking</button>
<button ng-click="stopTracking(person)">Stop tracking</button>
<p>{{person.name}}</p>
<ul>
<li ng-repeat="pos in person.positions">{{pos.position}}</li>
</ul>
</div>
And the directive would be called this way
<div ng-repeat="person in people">
<div position></div>
</div>
I'm not saying that this is a better solution but that is how I would do it. Remember it is just a model and needs a lot of improvement.
I'm trying to learn firebase/angularjs by extending an app to use firebase as the backend.
My forge looks like this
.
In my program I have binded firebaseio.com/projects to $scope.projects.
How do I access the children?
Why doesn't $scope.projects.getIndex() return the keys to the children?
I know the items are in $scope.projects because I can see them if I do console.log($scope.projects)
app.js
angular.module('todo', ['ionic', 'firebase'])
/**
* The Projects factory handles saving and loading projects
* from localStorage, and also lets us save and load the
* last active project index.
*/
.factory('Projects', function() {
return {
all: function () {
var projectString = window.localStorage['projects'];
if(projectString) {
return angular.fromJson(projectString);
}
return [];
},
// just saves all the projects everytime
save: function(projects) {
window.localStorage['projects'] = angular.toJson(projects);
},
newProject: function(projectTitle) {
// Add a new project
return {
title: projectTitle,
tasks: []
};
},
getLastActiveIndex: function () {
return parseInt(window.localStorage['lastActiveProject']) || 0;
},
setLastActiveIndex: function (index) {
window.localStorage['lastActiveProject'] = index;
}
}
})
.controller('TodoCtrl', function($scope, $timeout, $ionicModal, Projects, $firebase) {
// Load or initialize projects
//$scope.projects = Projects.all();
var projectsUrl = "https://ionic-guide-harry.firebaseio.com/projects";
var projectRef = new Firebase(projectsUrl);
$scope.projects = $firebase(projectRef);
$scope.projects.$on("loaded", function() {
var keys = $scope.projects.$getIndex();
console.log($scope.projects.$child('-JGTmBu4aeToOSGmgCo1'));
// Grab the last active, or the first project
$scope.activeProject = $scope.projects.$child("" + keys[0]);
});
// A utility function for creating a new project
// with the given projectTitle
var createProject = function(projectTitle) {
var newProject = Projects.newProject(projectTitle);
$scope.projects.$add(newProject);
Projects.save($scope.projects);
$scope.selectProject(newProject, $scope.projects.length-1);
};
// Called to create a new project
$scope.newProject = function() {
var projectTitle = prompt('Project name');
if(projectTitle) {
createProject(projectTitle);
}
};
// Called to select the given project
$scope.selectProject = function(project, index) {
$scope.activeProject = project;
Projects.setLastActiveIndex(index);
$scope.sideMenuController.close();
};
// Create our modal
$ionicModal.fromTemplateUrl('new-task.html', function(modal) {
$scope.taskModal = modal;
}, {
scope: $scope
});
$scope.createTask = function(task) {
if(!$scope.activeProject || !task) {
return;
}
console.log($scope.activeProject.task);
$scope.activeProject.task.$add({
title: task.title
});
$scope.taskModal.hide();
// Inefficient, but save all the projects
Projects.save($scope.projects);
task.title = "";
};
$scope.newTask = function() {
$scope.taskModal.show();
};
$scope.closeNewTask = function() {
$scope.taskModal.hide();
};
$scope.toggleProjects = function() {
$scope.sideMenuController.toggleLeft();
};
// Try to create the first project, make sure to defer
// this by using $timeout so everything is initialized
// properly
$timeout(function() {
if($scope.projects.length == 0) {
while(true) {
var projectTitle = prompt('Your first project title:');
if(projectTitle) {
createProject(projectTitle);
break;
}
}
}
});
});
I'm interested in the objects at the bottom
console.log($scope.projects)
Update
After digging around it seems I may be accessing the data incorrectly. https://www.firebase.com/docs/reading-data.html
Here's my new approach
// Load or initialize projects
//$scope.projects = Projects.all();
var projectsUrl = "https://ionic-guide-harry.firebaseio.com/projects";
var projectRef = new Firebase(projectsUrl);
projectRef.on('value', function(snapshot) {
if(snapshot.val() === null) {
console.log('location does not exist');
} else {
console.log(snapshot.val()['-JGTdgGAfq7dqBpSk2ls']);
}
});
$scope.projects = $firebase(projectRef);
$scope.projects.$on("loaded", function() {
// Grab the last active, or the first project
$scope.activeProject = $scope.projects.$child("a");
});
I'm still not sure how to traverse the keys programmatically but I feel I'm getting close
It's an object containing more objects, loop it with for in:
for (var key in $scope.projects) {
if ($scope.projects.hasOwnProperty(key)) {
console.log("The key is: " + key);
console.log("The value is: " + $scope.projects[key]);
}
}
ok so val() returns an object. In order to traverse all the children of projects I do
// Load or initialize projects
//$scope.projects = Projects.all();
var projectsUrl = "https://ionic-guide-harry.firebaseio.com/projects";
var projectRef = new Firebase(projectsUrl);
projectRef.on('value', function(snapshot) {
if(snapshot.val() === null) {
console.log('location does not exist');
} else {
var keys = Object.keys(snapshot.val());
console.log(snapshot.val()[keys[0]]);
}
});
$scope.projects = $firebase(projectRef);
$scope.projects.$on("loaded", function() {
// Grab the last active, or the first project
$scope.activeProject = $scope.projects.$child("a");
});
Note the var keys = Object.keys() gets all the keys at firebaseio.com/projects then you can get the first child by doing snapshot.val()[keys[0])