Cakephp JsHelper and SVG - cakephp

Is it possible to bind in cakephp an event to a svg node element ?
I have the RequestHandler working correctly with divs, but i was
asked to set in the page a SVG that has several clickable areas.
If i do something like the following code:
<object id="mysvg" type="image/svg+xml" data="/img/mysvg.svg">
<p>Error, browser must support "SVG"</p>
</object>
and then add the jshelper code:
$this->Js->get('#mysvg-nodeID')->event('click', $this->Js->request(
array('action' => 'myaction', 'param01'),
array('async' => true, 'update' => '#main_div')));
It doesn't seem to work.
Can anyone share some thoughts ?
Best regards

Answering my own question in case some else also needs this.
There's probably a better solution, please share if you find one :)
Anyway, this one serves it's purpose. As i din't find a way to get
the event associated to the svg node i added javascript for that part.
<script type="text/javascript">
//<![CDATA[
var a = document.getElementById("mysvg");
//it's important to add an load event listener to the object, as it will load the svg doc asynchronously
a.addEventListener("load",function(){
var svgDoc = a.contentDocument; //get the inner DOM
var delta = svgDoc.getElementById("mysvg-nodeID"); //get the inner element by id
delta.addEventListener("mousedown",
function(){
<?php
echo $this->Js->request(array('action' => 'myaction', 'param01'),array('async' => true, 'update' => '#main_div'));
?>
},false); //add behaviour
</script>

Related

Unable to have an ol3 map in each angular module

I'm using openlayers3 (ol3) and angular 1.5.6 on IE Edge.
I have two modules. Each has their own controller and component. Each controller wants to have a map in the view. One view is for interactively querying data off its map. The other view is for displaying interactive query results.
Under the hood, I provide a MapFactory which returns an instance of a object, containing the said openlayers map.
PROBLEM: The one displays while the other does not.
Here's a sample of my code (some details are left out for simplicity. For example the dependency injection checks. All of this code is being called as expected.):
Module A definition
angular.module('ModuleA').controller('ModuleAController',ModuleAController);
ModuleAController.$inject = ['MapFactory'];
function ModuleAController(MapFactory){
var vm = this;
var vm.map = MapFactory.getMapInstance({
id:'module-A-map',
otherOption:true
});
}
In ModuleA's view:
<div id='module-A-map' class="map-classes"></div>
Module B definition
angular.module('ModuleB').controller('ModuleBController',ModuleBController);
ModuleBController.$inject = ['MapFactory'];
function ModuleBController(MapFactory){
var vm = this;
var vm.map = MapFactory.getMapInstance({
id:'module-B-map',
otherOption:true
});
}
In ModuleB's view:
<div id='module-B-map' class="map-classes"></div>
MapFactory's definition:
angular.module('common').factory('MapFactory',MapFactory);
MapFactory.$inject = [];
function MapFactory(){
var factory = {
getMapInstance : getMapInstance
};
return factory;
function getMapInstance(options){
return new _MapConstructor(options);
}
function _MapConstructor(options){
var _map = new ol.Map({
target : options.id,
logo : false,
view : new ol.View({...}),
layers : [some,layers,here]
});
return {
publicMethod : publicMethod
};
function publicMethod(){...}
function privateMethod(){...}
... other stuff ...
}
}
Please, let me know if any clarification is needed to answer the question.
MORE:
This issue: https://github.com/openlayers/ol3/issues/4601 might be part of the problem. I am using collapsable DIVs with bootstrap. The ModuleA is in the default displayed one, while ModuleB is hidden at first. More to come.
I wrote this up as an OL3 issue as well: https://github.com/openlayers/ol3/issues/5789
ABSTRACT ANSWER:
http://getbootstrap.com/javascript/#collapse-events
I need to add a _map.updateSize() on a show.bs.collapse or shown.bs.collapse event. Now, I need to figure out how to do that in Angular, and post it (unless somebody gets to it first).
Ah, this is in Bootstrap's collapse class. So, let's back up to the Module-B view. Each of my Module's is a panel within a Bootstrap panel accordian. The ModuleA map that displays is the default open panel (the one that has the in class). The ModuleB map is not open by default, and thus, OL3 gives the canvas a display:none in the map's div's style.
<div id="module-B-collapse" class="panel-collapse collapse" >
<div id='module-B-map' class="map-classes"></div>
....
</div>
In my ModuleBController, I simply added:
angular.element('#module-B-collapse').on('shown.bs.collapse',function(){
_map.updateSize();
});

angular directive: infinite nesting using ng-include, model update does mess up view

I just found out, that when using the infinite structure in a directive on every model update, the template will get messed up on too many ng-changes. This is caused by the ng-include (I figured out). I use somekind of this in my directive's template via templateUrl, which is written in HAML:
.btn-group{ :name => "FIXME", "ng-required" => "true" }
%a.btn.btn-default.dropdown-toggle{ "data-toggle" => "dropdown", href: "#", "ng-disabled"=>"ngDisabled" }
{{currentValue.name || dropdownPlaceholder }}
%span.caret
%ul.dropdown-menu{ "ng-show" => "!ngDisabled" }
%div{ "ng-repeat" => "model in ngModel", "ng-include" => "'node.html'" }
%script{ :type => "text/ng-template", :id => "node.html" }
%li{ "ng-click" => "selectValue(model)" }
%a
{{model.name}}
%ul{ "ng-repeat" => "model in model.children", :style => "margin-left: 10px;" }
%div{ "ng-include" => "'node.html'" }
on many clicks on the dropdown the view seems to keeps the old items and seems to push the new ones additionally, even though the debug states the model is updating correctly and clean (checked also in directives model). I get an buggy output like this:
https://dl.dropboxusercontent.com/u/21600359/Bildschirmfoto%202013-10-13%20um%2001.31.30.png
Does anybody can give me a hint on how to have ng-include refresh and rebuild the directives template tree like structure?
I really appreciate!
kind regards,
Alex

View is not showing in backbone.marionette

I was trying to build an example to demonstrate the region and layout thing of Backbone.Marionette . But i stuck in the layout , though i am calling the layout.region.show() , it's not showing anywhere in the DOM.
Full example can be found in this JsFiddle.
This is the layout part :
AppLayout = Backbone.Marionette.Layout.extend({
template: "#layout-template",
el : "layout-containr",
regions: {
menu: "#menu",
content: "#content"
}
});
Layout template:
<script id="layout-template" type="text/template">
<section>
<div id="menu"></div>
<div id="content"></div>
</section>
Here is how i am showing the layout :
var layout = new AppLayout();
layout.render();
layout.menu.show(gridView);
GridView's definition can be found here:
var GridView = Backbone.Marionette.CollectionView.extend({
itemView: GridRow,
el:'#menu'
});
Full example can be found in this JsFiddle.
And i have a complimentary question :
How layout will know where it should be attached ???
I did not find it anywhere in the net which makes me sure that i am missing some concepts here.
You need a bigger region to show the layout, in application level.
Usually when you initialize a Marionette application, you will have some top-leve regions to show the layout you want to render later.
App.addInitializer =>
App.addRegions
menuRegion: '#header'
contentRegion: '#stage' # These DOM come from your application layout
And then in your controller, you show these layout in your top-leve region.
indexShow: ->
layout = new App.Layouts.SomeLayout()
App.contentRegion.show(layout)
someView = new App.Views.SomeView()
anotherView = new App.Views.AnotherView()
layout.someSubRegion.show(someView)
layout.anotherSubRegion.show(anotherView)
And, you usually don't need an el either in your view or layout

ExtJs - Get element by div class?

How do I get the ExtJs component object of a Div by class name?
Say my div is:
<div class="abc"></div>
How do I get the ExtJs object of this Div to perform e.g. getWidth()
Note: There is no id given.
What I tried:
Ext.select(".abc")
Ext.query(".abc")
Edit:
Error:
Object has no method 'getWidth'
<div id="main">
<div class="abc"></div>
</div>
var d = Ext.get( "main" );
d.query('.abc').getWidth();
Use
var dom = Ext.dom.Query.select('.abc');
var el = Ext.get(dom[0]);
This will return an Ext.Element. You can then use ext methods on el like so
el.on('click', function(){}, scope);
or
el.getWidth()
I believe you mean Ext.dom.Element (not ExtJs component object). If yes try this code
var d = Ext.get( "main" );
alert(d.down('.abc').getWidth());​
demo
For Ext4 and up you could use the following:
Ext.ComponentQuery.query('panel[cls=myCls]');
And you will get and array of this components
source: http://docs.sencha.com/ext-js/4-1/#!/api/Ext.ComponentQuery
Ext.select('abc');
This method works in EXT 4 also.
In your example, just remove the dot when calling the string of the class name.

CakePHP: Adding meta nofollow tag to layout from view

I want to be able to add a meta tag from a view (or controller if possible) in CakePHP
I have a page like /mycontroller/myview but when it is accessed with filters like:
/mycontroller/myview/page:2/max_price:500
Then I want to add meta no follow tags.
There is a meta method on the HtmlHelper class.
When I call it like this:
$this->Html->meta('keywords', 'test test test', array('inline'=>false));
It creates a meta tag like this:
<meta name="keywords" content="test test test" />
However, when I call it like this:
$this->Html->meta('robots', 'noindex, nofollow', array('inline'=>false));
I would naturally expect and want it to create this:
<meta name="robots" content="noindex, nofollow" />
Instead I get this though:
<link href="http://www.example.com/mycontroller/noindex, nofollow" type="application/rss+xml" rel="alternate" title="robots" />
What am I doing wrong?
From the documentation page (last line)
If you want to add a custom meta tag then the first parameter should be set to an array. To output a robots noindex tag use the following code:
echo $this->Html->meta(array('name' => 'robots', 'content' => 'noindex'));
In your case:
echo $this->Html->meta(array('name' => 'robots', 'content' => 'noindex, nofollow'),null,array('inline'=>false));
Hope this helps
Here's a tweaked version of the code from this page. I've tested it, and it does work:
<?php
echo $this->Html->meta(
array('name' => 'robots', 'content' => 'noindex, nofollow'),
null,
array('inline'=>false));
?>
Obviously you can write this in a single line -I just broke it down for ease of viewing here.
You can set variables from the view to the layout in the same way you set from controller to view using $this->set(), I would have a setup like this:
// View
if($condition) {
$this->set('nofollow', true);
}
// Layout (in <head>)
if(isset($nofollow) && $nofollow) {
echo $this->Html->meta(array('name' => 'robots', 'content' => 'noindex, nofollow'));
}
Now you have a short 1-liner to add the nofollow directive from any view file.

Resources