KevinM1
Moderators-
Posts
5,222 -
Joined
-
Last visited
-
Days Won
26
Everything posted by KevinM1
-
Yeah, that's more or less what I thought, but just wanted to make sure I wasn't missing anything obvious. Thanks!
-
This will be my first attempt at using OOP to make a fully functional, real project. The law firm at which my brother works wants their site redone, and he suggested me. Unfortunately, most of my PHP experience is in the form of writing code that modifies/improves existing systems. I've never created one from scratch before. The firm's site already has a simple CMS. One that allows one of the secretaries to add a new lawyer bio and/or text for other pages, but not the ability to add items to the navigation menu or change any of the existing main graphics. I believe, however, that they can add images to the pages (such as a new laywer's photo). There doesn't appear to be too much in the way of database info. Most of the pages on the current site appear to be static, from what I can see. With the exception of the admin area - which is where the secretary goes to add/modify pages on the site - there's no membership to speak of. I'm thinking, for the public side of the site, to use a Front Controller. Would I need anything else? In particular, are there any other patterns I should think of (Registry, Command, etc)? The admin backend seems a bit more tricky. Obviously, there needs to be a simple login system, but I'm having trouble trying to see how to handle both the creation of new pages, and the editing of existing pages. In particular, how would I handle the text input? Simple textarea field? Embedded TinyMCE editor? Something else? What about a file naming scheme? Should I just use a numeric id (probably the easiest in terms of mapping the files to the database)? Something more user friendly? This is the part that will trip me up the most, so any input here would be greatly appreciated.
-
I'm not sure if this is more suited to the design forum, so please feel free to move it there. Is there any reason to use the Command pattern if you're already employing a Front Controller? Both are pretty similar (albeit different in size and scope). I'm just wondering what the general consensus is regarding a 'real' project (CMS, blog, that sort of thing).
-
I've been doing some freelance work for a local organization for the last few years. Recently, they hired a new director, and sent out a generic e-mail looking for a new director with web development experience. Naturally, I got suspicious, but figured that the director would at least send some word about moving in another direction. This was about a month ago, just before my old PC died. I just got my new PC earlier in the week, after spending a few weeks trying to fix the old one. I checked the website today, and low and behold 90% of it has changed (and not for the better). All that remains is my dropdown navigation system (which looks completely out of place now) and, ironically, my name as the current web designer. I'd like to remove those files that control the navigation system, but I'm weary about any legal ramifications that may have. I didn't copyright those files per se, but my name is on them. I don't want some wannabe Photoshop jocky passing off my work as their own. Should I just remove them regardless?
-
Form/validation classes (hypothetical designs)
KevinM1 replied to KevinM1's topic in PHP Coding Help
No that was a mistake. Anyway, it's not the best example. Try this: <?php abstract class FormInput { protected $name; protected $value; private static $classSuffix = 'Input'; protected function __construct($name, $value = null){ $this->name = $name; $this->value = $value; } public static function factory($type, $name){ $class = ucfirst($type) . self::$classSuffix; return new $class($name); } public function setValue($value){ $this->value = $value; } public function getValue(){ return $this->value; } } class EmailInput extends FormInput {} interface ValidatorStrategy { public function isValid(FormInput $input); } class FormValidator { private static $classSuffix = 'Validator'; private $strategies = array(); public function getStrategy(FormInput $input){ $class = get_class($input) . self::$classSuffix; if(!isset($strategies[$class])){ $strategies[$class] = new $class; } return $strategies[$class]; } public function isValid(FormInput $input){ return $this->getStrategy($input)->isValid($input); } } class EmailInputValidator implements ValidatorStrategy { const REGEX = '/^[_\.0-9a-zA-Z-]+@([0-9a-zA-Z][0-9a-zA-Z-]+\.)+[a-zA-Z]{2,6}$/'; public function isValid(FormInput $input){ return (bool) preg_match(self::REGEX, $input->getValue()); } } $validator = new FormValidator(); $email = FormInput::factory('email', 'useremail'); $email->setValue('foo@foobarred.com'); var_dump($validator->isValid($email)); ?> Awesome, thanks! As an added bonus, I didn't realize that one could implement Strategy without having the client (in this case, FormInput) having a Strategy object as one of its properties. I believe Zandstra's book had the quiz test and seminar pricing Strategies as parts of their clients, so I thought that was an integral part of the pattern. I'm glad to see it's not, though. EDIT: did the 'Topic Solved' button go away? -
Form/validation classes (hypothetical designs)
KevinM1 replied to KevinM1's topic in PHP Coding Help
Okay, I see it now. I was forgetting that the name property would be static, so the self::$classSuffix bit confused me. Just to be clear, the $type in FormValidator's isValid() method comes from FormInput, via Strategy, correct? -
Form/validation classes (hypothetical designs)
KevinM1 replied to KevinM1's topic in PHP Coding Help
That syntax is really throwing me off. I'm assuming that it's supposed to be placed within the superclass, but I'm not sure exactly how it works. What is $suffix? Does appending self actually append the current class name? In other words, is the following more or less on the right track? <?php class FormInput{ //using just the first example public __construct($text){ $class = ucfirst($text).self; //leaving out $suffix because I'm not sure what it's supposed to be return new $class; } } $password = new FormInput('password'); //returns an instance of PasswordFormInput ?> Or am I way off? -
Form/validation classes (hypothetical designs)
KevinM1 replied to KevinM1's topic in PHP Coding Help
Ah, good point on the former. I'm not quite seeing how a type/class name factory scheme would actually work, though. It seems a bit recursive, as it sounds as though you're suggesting using a type to retrieve itself. I'm sure I'm missing the point, though. -
Form/validation classes (hypothetical designs)
KevinM1 replied to KevinM1's topic in PHP Coding Help
Ah, good point, given their variety. I was thinking, my form idea may be better suited to a factory class that serves the right kind of form input based on their type. Something like: <?php class FormInputFactory{ //say that three times fast static public getInput($type, $name, $value=NULL, $id=NULL, ... /*the other optional parameters*/){ switch($type){ case 'text': return new TextInput($name, $value, $id); break; case 'password': return new PasswordInput($name, $value, $id); break; . . . } } } $textInput = FormInputFactory::getInput('text', 'username'); $passwordInput = FormInputFactory::getInput('password', '', 'specialInput'); //empty value, but an id for those CSS/JavaScript users ?> -
It's been a while since I've done any coding, since my PC has been broken for a few weeks. One of the things I have been thinking of is a way to implement forms in an OOP manner. It's been one of the things that's continued to bug me since I tried that experimental "Procedural to OOP" thread months back. I'm thinking that two classes are in order. A generic form class, which houses an array of form input objects and basically sticks the opening and closing form tags in the right place. The form inputs should all derive from the same superclass. One hangup: textareas are a bit different than most inputs, if memory serves. So, at first blush (and this is off the top of my head), something like: <?php class Form{ private inputs; public addInput(FormInput $input, $key){ $this->inputs[$key] = $input; } public removeInput($key){ if(!array_key_exists($key, $this->inputs){ echo "Cannot find form input with an ID of $key."; //I know, I know...I should subclass Exception here } else{ array_splice($this->inputs, $key, 1); } } public printForm(){ $output = "<form>"; foreach($this->inputs as $input){ $output .= $input->printInput(); } $output .= "</form>"; echo $output; } } abstract class FormInput{ protected $type; protected $name; protected $value; protected $size; protected $maxlength; protected $checked; protected $src; protected $id; //for those who like using CSS id's or JavaScript public __construct($type, $name, $value, $id=NULL, $size=NULL, $maxlength=NULL, $checked=NULL, $src=NULL){ $this->type = $type; $this->name = $name; $this->value = $value; $this->id = $id; $this->size = $size; $this->maxlength = $maxlength; $this->checked = $checked; $this->src = $src; } public printInput(){ $output = "<input type='$type' name='$name' value='$value' id='$id' size='$size' maxlength='$maxlength' checked='$checked' src='$src' />"; return $output; } } class TextInput extends FormInput{} class PasswordInput extends FormInput{} ?> Looking at it, I think it could work. One thing that immediately springs to mind is that I probably shouldn't put all required attributes in the FormInput class, as some of that stuff doesn't belong in certain inputs (for instance, a text input won't ever be 'checked'). A better way would probably be to put the bare minimum in the superclass - type, name, value, and id - and separate the rest. I'm unsure how deep to go with inheritence, though. The easiest, most flexible way to do it would probably be: <?php abstract class FormInput{ protected $type; protected $name; protected $value; protected $id; public __construct($type, $name, $value, $id=NULL){ $this->type = $type; $this->name = $name; $this->value = $value; $this->id = $id; } } class CheckboxInput extends FormInput{ private $checked; public __construct($type, $name, $value, $id=NULL, $checked){ parent::__construct($type, $name, $value, $id); $this->checked = $checked; } public printInput(){ $output = "<input type='$type' name='$name' value='$value' id='$id' checked='$checked' />"; return $output; } } ?> I think I'm more or less on the right track. The big question is whether or not something like this is actually worth implementing. I guess the most use could come from either a built-in validator, or, since this is OOP, perhaps a set of validation Decorators. The big Form class could have a validate() method that iterates through the inputs array, causing each decorator to fire. So, thoughts? Is this something worth fleshing out (add in textarea support, for example)? Or is it basically best used as a thought exercise?
-
Whoohoo! It's working like a charm. Thanks, guys!
-
Yeah, I only made one mask div to see if I could get the simplest case to work. I've already put in borders, but they didn't shed any light on the situation. You should probably take a look at my test page: http://www.nightslyr.com/scroll/test.html. The black-bordered div is the 'window' area. The blue-bordered div is the part that the scrolling image is supposed to hide behind. Right now, it's acting as though all elements have the same z-index.
-
I'm trying to get idea 2 to work, but it appears as though the z-indicies aren't working: HTML (JavaScript is the same as last time): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>scroll test</title> <script type="text/javascript" src="scroll.js"></script> </head> <body> <div id="container" style="width: 500px; height: 125px; position: absolute; padding: 0; margin: 0; top: 2px; left: 2px; z-index: 1; border: 1px solid black;"> <div id="scroll" style="position: absolute; left: -97px; width: 97px; z-index: 2;"> <img src="../Bergeron_Patrice.jpg" alt="" /> </div> </div> <div id="mask" style="width: 500px; height: 125px; position: absolute; padding: 0; margin: 0; top: 2px; left: 504px; z-index: 99; border: 1px solid blue;"> </div> </body> </html> As the image scrolls, I want it to hide behind the 'mask' div, but it's not disappearing. I'm not sure what I'm doing wrong, as I made all the divs absolutely positioned, which, according to what I've read, is the only way to get z-indicies to work. And, to add to my frustration, it fails in both IE and Firefox.
-
Thanks for the reply. I actually had a similar epiphany last night. I've almost got it 100% where I want it, but now there's some overlapping div issues. My ultimate goal was to create something of a window/mask that the image would move through. So, the image(s...I plan on expanding this once I get 1 image to work correctly) wouldn't be visible until it moved into that 'open' area. Now, I know how to do something like that using an element's background property, but trying to animate that seems a bit difficult to me at first blush, which is why I went the embedded div route. This will probably make more sense after seeing my code: HTML: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>scroll test</title> <script type="text/javascript" src="scroll.js"></script> </head> <body> <div id="container" style="width: 500px; height: 125px; border: 1px solid black;"> <div id="scroll" style="position: absolute; left: -97px; width: 97px;"> <img src="../Bergeron_Patrice.jpg" alt="" /> </div> </div> </body> </html> JavaScript: var W3CDOM = (document.createElement && document.getElementsByTagName); var count = 694; function init(){ if (!W3CDOM) return; var intervalId = setInterval("animate()", 200); } function animate(){ var scroll = document.getElementById('scroll'); var left = scroll.style.left; if(count != 0){ scroll.style.left = parseInt(left) + 1 + 'px'; count--; } else{ scroll.style.left = '-97px'; count = 694; } } window.onload = init; If you use this code, you'll see that my image starts off the screen on the left, moves through the container div, then out the other side before resetting. What I want it to do is not be visible until it starts moving through the container div. I tried messing with the elements' z-indicies, but that won't work as there's no way I can think of to essentially make the container div a window/mask that allows the other layers to show through. Other than that, it's working just as I had hoped.
-
Ah, duh...I must've stared at the code for an hour, and that didn't jump out at me. D'oh! So, now I have the image moving, and the animation correctly loops. There's only one more problem. I want each loop to have a several second delay (in this case, 3 seconds). Right now, the first loop is waiting 3 seconds before it begins (which I don't really want, but I can live with it), but each subsequent loop remains at the same speed, with no delay in between. I know what the problem is...when I return, I'm only going up one level of scope instead of the necessary two to pulse another animationController() interval. Updated code is below: var W3CDOM = (document.createElement && document.getElementsByTagName); var count = 500; function init(){ if (!W3CDOM) return; var mainIntervalId = setInterval("animationController()", 3000); } function animationController(){ var animateIntervalId = setInterval("animate()", 200); } function animate(){ var scroll = document.getElementById('scroll'); var left = scroll.style.left; if(count != 0){ scroll.style.left = parseInt(left) + 1 + 'px'; //see below count--; } else{ scroll.style.left = '2px'; //direct assigment in order to reset the loop count = 500; return; //clearInterval did nothing...this only returns me to animationController(). I need to get to init() } } window.onload = init; Any idea on how I can move back to init() from the else-block in animate()?
-
Was going to edit my last post, but I guess I took too long. New JavaScript code, same result as my last post: var W3CDOM = (document.createElement && document.getElementsByTagName); var count = 500; function init(){ if (!W3CDOM) return; var mainIntervalId = setInterval("animationController()", 3000); } function animationController(){ var animateIntervalId = setInterval("animate()", 200); } function animate(){ var scroll = document.getElementById('scroll'); var left = scroll.style.left; alert("Do I have the div: " + scroll); alert("Do I have the left-side: " + left); if(count != 0){ left = parseInt(left) + 1 + 'px'; count--; } else{ left = '2px'; count = 500; clearInterval(animateIntervalId); } } window.onload = init;
-
The good news is that my parse errors are gone. The bad news is that I have a logic error, so no animation is happening. My code is below: HTML: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>scroll test</title> <script type="text/javascript" src="scroll.js"></script> </head> <body> <div id="container"> <div id="scroll" style="position: absolute; left: 2px; width: 97px;"> <img src="../Bergeron_Patrice.jpg" alt="" /> </div> </div> </body> </html> JavaScript: var W3CDOM = (document.createElement && document.getElementsByTagName); var count = 500; function init(){ if (!W3CDOM) return; var timeoutId = setTimeout("animationController()", 3000); } function animationController(){ var intervalId = setInterval("animate()", 200); } function animate(){ var scroll = document.getElementById('scroll'); var left = scroll.style.left; alert("Do I have the div: " + scroll); alert("Do I have the left-side: " + left); if(count != 0){ left = parseInt(left) + 1 + 'px'; count--; } else{ left = '2px'; count = 500; return; } } window.onload = init; The strange thing is that both alerts are returning the right values -- I have access to the div, and it correctly reports that the left attribute is 2px. However, it seems that the extra pixel is not being added to the left side, as each loop reports that the left is set at 2px, when it should be incrementing. Is this just a case of me needing to set the value in the script itself and work with it that way, or is it possible for me to keep it as an inline style in the markup?
-
Thanks guys, I'll play with it today. Just to be clear, though, JavaScript, in general, has problems parsing styles found in external stylesheets? That seems...dumb . Is it some sort of legacy issue?
-
Well, like I said, this is just a test script, so virtually all of the code has already been shown.... HTML (test.html): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>scroll test</title> <link rel="stylesheet" type="text/css" href="styles.css" /> <script type="text/javascript" src="scroll.js"></script> </head> <body> <img src="../Bergeron_Patrice.jpg" alt="" id="scrollImage" /> </body> </html> CSS (styles.css): #scrollImage { position: absolute; left: 2px; } JavaScript (scroll.js): var W3CDOM = (document.createElement && document.getElementsByTagName); var count = 500; function init(){ if (!W3CDOM) return; animationController(); } function animationController(scrollImage){ var intervalId = setInterval(animate, 200); setTimeout(animationController, 3000); } function animate(){ var scrollImage = document.getElementById('scrollImage'); alert("Do I have the image: " + scrollImage); alert("Left value: " + scrollImage.style.left); if(count != 0){ scrollImage.style.left = parseInt(scrollImage.style.left) + 1 + 'px'; alert("Left value: " + scrollImage.style.left); count--; } else{ scrollImage.style.left = '2px'; count = 500; return; } } window.onload = init;
-
I think I'm another step closer. My current code (with a couple alerts for debugging): var W3CDOM = (document.createElement && document.getElementsByTagName); var count = 500; function init(){ if (!W3CDOM) return; animationController(); } function animationController(scrollImage){ var intervalId = setInterval(animate, 200); setTimeout(animationController, 3000); } function animate(){ var scrollImage = document.getElementById('scrollImage'); alert("Do I have the image: " + scrollImage); alert("Left value: " + scrollImage.style.left); if(count != 0){ scrollImage.style.left = parseInt(scrollImage.style.left) + 1 + 'px'; alert("Left value: " + scrollImage.style.left); count--; } else{ scrollImage.style.left = '2px'; count = 500; return; } } window.onload = init; I hate the idea of using a global variable (count), but, so far, that's the only way I can come up with a possible solution to the counting issue. I can't seem to pass values to the functions in the setTimeout/setInterval functions, so this is the workaround I've come up with at the moment. My problem now is that, for some reason, the script can't parse the image's style property. For reference, my CSS is: #scrollImage { position: absolute; left: 2px; } Yet, my script can't seem to get a handle on that property. I AM getting a hold of the image itself, though, as the first alert box comes back okay. Again, any help would be appreciated.
-
Well, here's what I have so far: var W3CDOM = (document.createElement && document.getElementsByTagName); function init(){ if (!W3CDOM) return; var scrollImage = document.getElementById('scrollImage'); animationController(scrollImage); } function animationController(scrollImage){ var count = 500; var intervalId = setInterval("animate(scrollImage, count)", 200); setTimeout("animationController(scrollImage)", 3000); } function animate(scrollImage, count){ if(count != 0){ scrollImage.style.left = parseInt(scrollImage.style.left) + 1 + 'px'; count--; } else{ scrollImage.style.left = '2px'; return; } } window.onload = init; Unfortunately, it's not working. Specifically, Firebug keeps informing me that scrollImage is undefined in the animate function. I'm at a bit of a loss, so any help would be appreciated.
-
Well, I'm getting closer. I was able to get it working by doing the following: var W3CDOM = (document.createElement && document.getElementsByTagName); function init(){ if (!W3CDOM) return; var scrollImage = document.getElementById('scrollImage'); scrollImage.style.left = '2px'; //reset position on every page view, just in case animate(scrollImage); } function animate(scrollImage){ scrollImage.style.left = parseInt(scrollImage.style.left) + 10 + 'px'; setTimeout(animate(scrollImage), 2000); } window.onload = init; Now I'm having problems making a looping animation. Here's what I'm trying to do: slide an image 500 px to the right, then, once it gets there, start over. I tried the following code: var W3CDOM = (document.createElement && document.getElementsByTagName); function init(){ if (!W3CDOM) return; var scrollImage = document.getElementById('scrollImage'); var count = 500; animate(scrollImage, count); } function animate(scrollImage, count){ if(count != 0){ scrollImage.style.left = parseInt(scrollImage.style.left) + 1 + 'px'; --count; setTimeout(animate(scrollImage, count), 200); } else{ count = 501; scrollImage.style.left = '2px'; setTimeout(animate(scrollImage, count), 200); } } window.onload = init; But Firebug is saying I have too much recursion going on. What I'd ultimately like to do is this: Have the image move 500px to the right. Once it's there, wait several seconds before restarting the loop. So, I'm thinking that using one function with a timeout, with a nested interval function which would return after the count reaches zero is the way to go, but I'm not 100% sure how to code it up. Any ideas?
-
I'm currently trying my hand at simple JavaScript animation since I don't know Flash. Unfortunately, I cannot get a simple test script to work properly. The JavaScript is: var W3CDOM = (document.createElement && document.getElementsByTagName); function init(){ if (!W3CDOM) return; var scrollImage = document.getElementById('scrollImage'); scrollImage.style.left = '2px'; //reset position on every page view, just in case animate(scrollImage); } function animate(scrollImage){ scrollImage.style.left = parseInt(scrollImage.style.left) + 10 + 'px'; setTimeout(animate, 2000); } window.onload = init; With this code, I keep getting a "scrollImage.style has no properties" error in Firefox, and something similar in IE. This isn't the case, though, as I have some simple CSS defined for it: #scrollImage { position: absolute; left: 2px; } Here's the thing: I can get it to work in IE if I don't pass the image to the function. This results in scrollImage being undefined in Firefox, leading me to believe my main problem is one of scope. Unfortunately, I'm not sure how to work around it (I thought that passing the image to the function would fix it, but instead it broke the script in both browsers). Any ideas? Thanks!
-
If I recall correctly, he's saying that using native PHP is faster, but using a storage method such an XML file is more flexible and caching a resulting object can be nearly as fast. If not, that's what he should be saying. Okay, so in other words, keeping config data as a PHP file is faster, as you can include/require it directly where necessary, but using an XML file (for example) is more flexible for the end user? Makes sense.
-
After a bit of a break for the holidays (and the company I did part-time work for closing down), I'm now back in the swing of trying to grasp larger OOP concepts. I have downloaded Code Igniter, but I want to get some of the theory down before looking at a bulk of code. My questions stem from reading Zandstra's PHP 5: Objects, Patterns, and Practice book. Am I correct in viewing his Woo_Request class as being analogous to the Command pattern's CommandContext/RequestHelper class? He mentions the problem of caching setting/configuration data and suggests using PHP itself. What does he mean by that? Overall, am I correct in viewing the general process as being: 1. Single point of entry (say, index.php). 2. All links having a recognized $_GET value. The links themselves merely point back to the index page (say, "index.php?cmd=feedback"). 3. When that request is delivered via the page reloading (since every link points back to itself), that's when the controller fires, serving up the right page based on the request. If I'm more or less on the right track, I'll move onto figuring out Code Igniter's method of generating nice pathnames that reflect site navigation rather than ugly $_GET-filled URLs (so, "index.php/feedback" instead of "index.php?cmd=feedback").