SilverStripe change $menu_icon in CMSPageController - silverstripe

I'm trying to change the $menu_icon variable in CMSPageController without editing core files (IE: the icon next to menu item "Pages" in the CMS). I went on a limb and tried the following:
1: Define an extension to CMSPageController in _config.yml
CMSPageController:
extensions:
- ChangeMenuIcon
2: Define class and extend from CMSPageControllerExtension in mysite
class ChangeMenuIcon extends CMSPageControllerExtension {
private static $menu_icon = 'framework/admin/images/menu-icons/16x16/information.png';
}
This results in a 500 error. Is this actually the correct way to overwrite an existing (core) class property?

Faloude, since it's a private static you could try setting it directly in the config.yml rather than applying an extension.
CMSPagesController:
menu_icon: 'framework/admin/images/menu-icons/16x16/information.png';

Related

Preparing for Internationalization of Asp.net MVC website

I'm going to start a website which I know is going to be presented in multiple languages. However, for the first version we're only going to need the English version. Once the features are all working, we'll add the other languages.
Unfortunately since there are not enough enough features baked into Asp.Net Core, we have to use the Asp.Net MVC 5 for the website. My question has 2 parts:
Right now, which practice is considered the best approach for this? Using resource files and loading them in razor pages? Using a framework? Can we use the new localization and globalization features of Asp.Net MVC 6 somehow? Or is there a better alternative? I personally hate using the resource files. It adds too much clutter to the code.
Would you suggest just using plane text for now and then adding the Internationalization features to the website or start now and only add the translations?
I would use resource files, seems to be the easiest solution. You can also use a Database resource provider, so you have less clutter.
If you start with plain text, it will get more complicated and cumbersome to add the translations later. So I would not do that.
We use Smart internationalization for ASP.NET.
Features
Localize everything: HTML, Razor, C#, VB, JavaScript, .NET attributes
and data annotations, ...;
SEO-friendly: language selection varies the URL, and Content-Language is set appropriately;
Automatic: no URL/routing changes required in the app;
High performance, minimal overhead and minimal heap allocations; Unit testing support;
Smart: knows when to hold them, fold them, walk away, or run, based on i18n best practices.
How I use i18n in the project step by step:
Add the I18N nuget package to your MVC project.
in Web.config:
Add a folder named "locale" to the root of your site. Create a subfolder for each culture you wish to support. For example, /locale/fr/.
copy i18n.PostBuild.exe into locale folder
Right click on tne project name --> Properties --> Build Events:
in Post-build event command line:
"$(TargetDir)i18n.PostBuild.exe" "$(ProjectDir)\web.config"
In views use [[[some text]]] to translate it later
Build the project
Refresh Solution Explorer and push Show All Files
Include all files in "locale" folder into the project
Provide translation of the words in locale\fr\messages.po
In Global.aspx add :
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//other app start code
UrlLocalizer.UrlLocalizationScheme = UrlLocalizationScheme.Void;
}
}
Create DefaultController :
public class DefaultController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
if (Session["currentLanguage"] == null)
{
Session["currentLanguage"] = "en";
}
}
}
In HomeController add inheritance of DefaultController and SwitchLanguage(string lang):
public class HomeController : DefaultController
{
public HomeController() : base()
{
[AllowAnonymous]
public async Task<ActionResult> SwitchLanguage(string lang)
{
LocalizedApplication.Current.DefaultLanguage = lang;
Session["currentLanguage"] = lang;
return Redirect(Request.UrlReferrer.PathAndQuery);
}
}
}
In navigation bar View (_LoginPartial.cshtml in my case) add links to switch between languages:
#if (Session["currentLanguage"].ToString() == "fr")
{
<li class="navItem">#Html.ActionLink("EN", "SwitchLanguage", "Home", new { lang = "en", area = "" }, null)</li>
}
else
{
<li class="navItem">#Html.ActionLink("FR", "SwitchLanguage", "Home", new { lang = "fr", area = "" }, null)</li>
}
Build project, Start in Browser and enjoy!!!
see some help in:
https://www.codeday.top/2017/09/19/42409.html

How to add JS and CSS to all content parts in an Orchard module

I am writing a module for Orchard CMS 1.8.1
I would like to add custom styles to all content parts that I have written for the module. I need these to work regardless of the theme chosen by the website admins. I could add links to the CSS and JS files in every view file for every content part - but that seems messy and prone to future bugs - what's the best way to have a single file that loads up the styles needed for all my content parts?
Should I provide a different Content.cshtml that includes the links? This also seems like it could be problematic if the admins need their own control over the main Content.cshtml
Many thanks
Handler should do the trick, I wrote this from the top of my head so not sure if it really works.
First create ResourceManifest.cs and define your stylesheets and scripts
public class ResourceManifest : IResourceManifestProvider
{
public void BuildManifests(ResourceManifestBuilder builder)
{
var manifest = builder.Add();
manifest.DefineStyle("MyStylesheet").SetUrl("mystylesheet.min.css", "mystylesheet.css").SetVersion("1.0.0");
manifest.DefineScript("MyScript").SetUrl("myscript.min.js", "myscript.js").SetVersion("1.0.0");
}
}
Then it should be enough to create content handler and override the BuildDisplayShape
public class MyResourceHandler : ContentHandler
{
private readonly Work<IResourceManager> _resourceManager;
public MyResourceHandler(Work<IResourceManager> resourceManager)
{
_resourceManager = resourceManager;
}
protected override void BuildDisplayShape(BuildDisplayContext context)
{
if (context.DisplayType == "Detail" && context.ContentItem.Has(typeof(MyPart)))
{
this._resourceManager.Value.Require("stylesheet", "MyStylesheet");
this._resourceManager.Value.Require("script", "MyScript");
}
base.BuildDisplayShape(context);
}
}
Adjust the IF as necessary. And let me know if it works ;)
Beauty of using ResourceManifest with versioning is that anyone can replace your stylesheets/javascript with their own just by defining style in their own ResourceManifest (module/theme) with same name and higher version number and don't have to touch any original files.

How do I manage library symbols with linked classes in Flash CS4 to compile/debug in Flash Builder 4?

I'm building a video player using Flash CS4 (hereby referred to as "Flash") to create the graphic symbols and compiling and debugging with Flash Builder 4 ("FB4"). Here are the steps I take in my current workflow:
--Create the graphic symbols in Flash. I've created a few different symbols for the player, but I'll focus on just the play/pause button ("ppbutton") here.
--In the Library panel, I go to the ppbutton symbol's Linkage properties and link to a class named assets.PlayPauseButtonAsset that extends MovieClip. I do not actually have an assets package nor do I have a class file for PlayPauseButtonAsset as Flash will create them for me when I publish.
--In Flash's Publish settings, I set the project to export a SWC that will be used in FB4, called VideoPlayerAssets.swc.
--After the SWC is created, I create my FB4 project called "VideoPlayer" and add the SWC to my path. FB4 creates the class VideoPlayer in the default package automatically.
--In VideoPlayer.as, I import assets.*, which imports all of the symbol classes I created in Flash and are available via VideoPlayerAssets.swc. I can now instantiate the ppbutton and add to the stage, like this:
var ppbutton:PlayPauseButtonAsset = new PlayPauseButtonAsset();
addChild(ppbutton);
At this point ppbutton doesn't have any functionality because I didn't create any code for it. So I create a new class called video.controls.PlayPauseButtonLogic which extends assets.PlayPauseButtonAsset. I add some logic, and now I can use that new class to put a working ppbutton on the stage:
var ppbutton:PlayPauseButtonLogic = new PlayPauseButtonLogic();
addChild(ppbutton);
This works fine, but you may be asking why I didn't just link the ppbutton symbol in Flash to the video.controls.PlayPauseButtonLogic class in the first place. The reason is that I have a designer creating the UI in Flash and I don't want to have to re-publish the SWC from Flash every time I make a change in the logic. Basically, I want my designer to be able to make a symbol in Flash, link that symbol to a logically named class in Linkage properties, and export the SWC. I do not want to have to touch that .fla file again unless the designer makes changes to the symbols or layout. I'm using a versioning system for the project as well and it's cleaner to make sure only the designer is touching the .fla file.
So, finally, here's the issue I'm running into:
--As the design gets more complex, the designer is nesting symbols to position the video controls on the control bar. He creates a controlbar symbol and links it to assets.ControlBarAsset. The controlbar symbol contains the ppbutton symbol.
--The designer publishes the SWC and ControlBarAsset is now available in FB4. I create new class called video.controls.ControlBarLogic that extends assets.ControlBarAsset so I can add some logic to the controlbar, and I add the controlbar to the stage:
var controlbar:ControlBarLogic = new ControlBarLogic();
addChild(controlbar);
--This works, but the ppbutton doesn't do anything. That's because ppbutton, while inside controlbar, is still only linked to PlayPauseButtonAsset, which doesn't have any logic. I'm no longer instantiating a ppbutton object because it's part of controlbar.
That's where I'm stuck today. I can't seem to simply re-cast controlbar's ppbutton as PlayPauseButtonLogic as I get a Type error. And I don't want to have to make a class that has to instantiate each of the video player controls, the place them at their x and y values on the stage according to how the designer placed them, as that would require me to open the .fla and check the various properties of a symbol, then add those values to the code. If the designer made a change, I'd have to go into the code each time just to update those properties each time. Not good.
How do I re-cast nested symbols to use the logic classes that I create that extend the asset classes? Remember, the solution is not to link Flash symbols to actual classes so I don't have to keep recompiling the SWC, unless there's a way to do that without having to re-compile the SWC. I want the designer to do his thing, publish the SWC, and be done with it. Then I can take his SWC, apply my logic to his assets, and be able to debug and compile the final SWF.
Here is the solution that i use sometimes:
Instead of making PlayPauseButtonLogic extends PlayPauseButtonAsset, use this class as a warpper of PalyPauseButtonAsset, use composition instead of inheritance ! ; ).
You will get something like this in your ControlBarLogic class:
//constructor exemple
public function ControlBarLogic(){
//all logic of PPButton is inside PlayPauseButtonLogic
//you just pass a reference to the PlayPauseButtonAsset button contained inside ControlBarAsset
var ppButtonLogic: PlayPauseButtonLogic=new PlayPauseButtonLogic(refToButtonAsset)
//the warper class can extends EventDispatcher so you will be able to listen to custom or redisatched events
ppButtonLogic.addEventListener("ppPause",onPause)
}
hope it will help you
You can have two classes, one holding functionality and the other providing its graphical implementation (asset/skin)
Have PlayPauseButtonLogic extend AssetWrapper.
A simple way to solve your issue regarding event listeners, you can do the following:
package {
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.IEventDispatcher;
public class AssetWrapper implements IEventDispatcher {
private var _skin:DisplayObjectContainer;
public function AssetWrapper( skin:DisplayObjectContainer = null ) {
if ( skin ) setSkin(skin);
}
public function setSkin(skin:DisplayObjectContainer):void{
_skin = skin;
}
public function dispatchEvent(event:Event):Boolean{
_skin.dispatchEvent(event);
}
public function hasEventListener(type:String):Boolean{
return _skin.hasEventListener(type);
}
public function willTrigger(type:String):Boolean{
return _skin.willTrigger(type);
}
public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
_skin.removeEventListener(type, listener, useCapture);
}
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
_skin.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
}
}
EDIT:
You can then, of course, just add as many properties/methods to AssetWrapper that delegate to the DisplayObject (skin) as you need. It also gives you more control onto those properties/methods.
i.e:
public function get x( ):Number {
return _skin.x;
}
public function set x( v:Number ):void {
if ( _skin.x = v ) return;
if ( _useWholePixels ) _skin.x = Math.round(v);
else _skin.x = v;
}
That way, for instance, you can tween your AssetWrapper instance directly. Also, you can control if you want it to be placed in round numbers (x=100) or not (x=100.5)
For methods, just the same idea:
public function addChild( child:DisplayObject ):DisplayObject {
return _skin.addChild( child );
}
Then to use it, you would extend AssetWrapper and implement a concrete behavior:
package {
import flash.display.DisplayObjectContainer;
import flash.events.MouseEvent;
public class SimpleButton extends AssetWrapper {
public function SimpleButton( skin:DisplayObjectContainer = null ) {
super(skin)
}
override public function setSkin( skin:DisplayObjectContainer):void {
super.setSkin( skin );
addEventListener(MouseEvent.ROLL_OVER, _onRollOver );
addEventListener(MouseEvent.ROLL_OUT, _onRollOut );
}
protected function _onRollOver(e:MouseEvent):void {
_skin.alpha = .5;
}
...
}
And you would use it as follows:
//you can get your graphical assets in many different ways
var buttonSkin:Sprite = new LibraryButtonSkin
//or
var ButtonSkinClass:Class = this.loaderInfo.applicationDomain.getDefinition("SimpleButtonSkin") as Class;
buttonSkin = new ButtonSkinClass;
var button:SimpleButton = new SimpleButton(buttonSkin);
button.addEventListener(MouseEvent.CLICK, _handleButton);
It is just a guide, in the real implementation you want to make sure you check for things like if a skin already exists, then remove all added listeners. You would probably could listen for an ADDED_TO_STAGE event and trigger a initialize method...
Also is a great to clean up after your instance by implement a destroy() method where you make sure all added listeners are removed and null/stop things like timers, sounds, etc.
Wow all the flow and we sunk in the finish line....
well, what about something like this
AbstractButtonBehavior
PlayButtonBehavior extends...
The trick, the graphic components should all implement some interface that allow them to pass a behavior at instantiation time, or even better, at runtime. The you just plug the login in, the logic will always remain outside and the poor assets will keep asking or answering to the same interface call, allowing you to work outside them.
could be?.

Flex: Stop TabNavigator from adding #HASH to URL

Ok I have a TabNavigator component that keeps added a hash (#) to the URL. I need to prevent this. I have it set to historyManagementEnabled="false" but it is still adding the # to the URL when it initializes.
The reason why adding this hash is such a problem is because, I am using .htaccess to give my URL a pretty URL like domain.com/designer/category/product/id when the page is really located at domain.com/product.php?pid=id So in order for my assets to load correctly I had to add a base tag like this:
<base href="http://www.MYDOMAIN.com/" />
But since I have this base tag set, whenever my flex app adds the # to the URL, the page is now automatically redirected to the homepage.
So I really need to figure out a way to stop the TabNavigator from adding the # to the URL.
Any ideas?
Thanks!!
Turn off the history management in your Flex Builder project settings (in the Flex Compiler settings).
I was able to fix it by extending the TabNavigator and overriding these functions:
package
{
import mx.containers.TabNavigator;
public class MyTabNav extends TabNavigator
{
public function MyTabNav()
{
super();
}
override public function get historyManagementEnabled():Boolean
{
return false;
}
override public function set historyManagementEnabled(value:Boolean):void
{
return;
}
}
}

How do you dynamically load two different CSS file into a Flex application?

i used blue.css and also beige.css in flex .i have theme combobox for user changed theme dynamically so i stroed
[Bindable]
private var pickcss:Array=["blue.css","beige.css"];
private function css_initializeHandler(event:Event):void
{
pickcssComboBox.selectedIndex = pickcss.indexOf(0);
}
private function css_changeHandler(event:Event):void
{
//here how will i apply
styleid= [ pickcssComboBox.selectedItem ];
}
" mx:Label text="Theme"/>
"mx:ComboBox id="pickcssComboBox" dataProvider="{pickcss}"
initialize="css_initializeHandler(event)"
change="css_changeHandler(event)" width="110"/>"
i used in style not have id so how can i do ? if u know plz explain
First, to load style sheets dynamically you need to compile them into separate .swf files. This can be done with mxmlc (or in Flex Builder by right-clicking on the css file and choosing "Compile CSS to SWF").
Then, to load the style-swf, you use the StyleManager
StyleManager.loadStyleDeclarations("blue.swf");
When you want to switch between styles, you'll also want to unload the previous style. So, assuming you put the name of css file in your combobox, in your css_changeHandler you'll do something like this:
StyleManager.unloadStyleDeclarations(styleid)
styleid = pickcssComboBox.selectedItem;
StyleManager.loadStyleDeclarations(styleid);
See Loading style sheets at run time for more details.

Resources