Add-ons
  1. Add-ons
  2. CONTRIB-4099

Grid format does not allow the user to set the size of the image / box.

    Details

    • Affected Branches:
      MOODLE_24_STABLE, MOODLE_25_STABLE, MOODLE_26_STABLE
    • Fixed Branches:
      MOODLE_25_STABLE, MOODLE_26_STABLE
    • Rank:
      47088

      Description

      Suggestion from Julian that the Grid format should provide a way of allowing the user to set the size of the image and its containing box through course settings in the same way that Collapsed Topics does with it's settings.

      I consider that this should be implemented in 2.5 as would not require a new database table and custom form.

      NOTE: The requirements below are now 99% finished. If you have any comments to make then please do so by 10th October 2013 or sooner.

      Requirements:

      1. Ability to set the width of the image container (icon) as a x in pixels and have the height calculated by a ratio. Widths of: 128, 192, 210, 256, 320, 384, 448, 512, 576, 640, 704 and 768. Ratios of: 3-2, 3-1, 3-3, 2-3, 1-3, 4-3 and 3-4.
      2. When uploading the maximum width size setting shall be applied to the image to avoid large file sizes in storage / downloading bandwidth.
      3. As a consequence of 1, up scaling the size of old courses will result in pixelation, therefore the user should re-upload an original copy of the image.
      4. Ability to change the border colour, radius (same as width and on / off setting) and width. Widths of: 1 - 10.
      5. Ability to change the image container (icon) background colour.
      6. Ability to change the current selected section colour with defaults.
      7. Ability to change the current selected image container (icon) colour with defaults.
      8. Width and ratio settings to be editable on the course settings form and stored in the config_plugin's table using existing 2.5+ core code.
      9. Default width, ratio, border colour, border radius on /off, border width, image container (icon) background colour settings to be made available to be set by the site administrator in 'Plugins -> Course formats'. Values to be transposed from current CSS style.
      10. Ability to reset to default the settings for the course in the 'Edit settings' of the course.
      11. Ability for the site administrator to reset to default the settings for all grid format courses.
      12. Ability for the site administrator to prevent setting changes through the implementation of custom capabilities in 'db/access.php' and checks in 'lib.php'. Two capabilities 'changeimagecontainersize' and 'changeimagecontainerstyle'.

      Proposal video: http://www.youtube.com/watch?v=G1zHTEdfP9o

        Activity

        Hide
        Gareth J Barnard added a comment -

        What would you all like in terms of functionality? I.e a list of available resolutions that have the right ratio, be able to enter width / height or enter width and have height calculated via a predefined ratio.

        Show
        Gareth J Barnard added a comment - What would you all like in terms of functionality? I.e a list of available resolutions that have the right ratio, be able to enter width / height or enter width and have height calculated via a predefined ratio.
        Hide
        llywelyn morgan added a comment -

        deciding own height and width would be great (or %).
        ability to centre an image.
        option to remove grey border or change it's colour (i know this can be done in css but may be handy for those who don't know how to).

        Show
        llywelyn morgan added a comment - deciding own height and width would be great (or %). ability to centre an image. option to remove grey border or change it's colour (i know this can be done in css but may be handy for those who don't know how to).
        Hide
        Gareth J Barnard added a comment -

        Dear Llywelyn,

        For centering, what do you think of requirement five?

        Cheers,

        Gareth

        Show
        Gareth J Barnard added a comment - Dear Llywelyn, For centering, what do you think of requirement five? Cheers, Gareth
        Hide
        Gareth J Barnard added a comment -

        Currently considering http://www.indiegogo.com/ as a means of funding this as for the money side of MDLSITE-2065.

        Show
        Gareth J Barnard added a comment - Currently considering http://www.indiegogo.com/ as a means of funding this as for the money side of MDLSITE-2065 .
        Hide
        llywelyn morgan added a comment -

        sorry for the late reply gareth. option 5 sounds fine.

        would be great if we could keep an image's existing size (larger than the grid window), but be allowed to move it and choose the centre position. a bit like when you choose avatars for different sites like facebook. however, i understand this would involve a lot more coding for an outcome that is't really necessary - it's easy enough to create custom made images.

        thumbs up for the funding option.

        Show
        llywelyn morgan added a comment - sorry for the late reply gareth. option 5 sounds fine. would be great if we could keep an image's existing size (larger than the grid window), but be allowed to move it and choose the centre position. a bit like when you choose avatars for different sites like facebook. however, i understand this would involve a lot more coding for an outcome that is't really necessary - it's easy enough to create custom made images. thumbs up for the funding option.
        Hide
        Gareth J Barnard added a comment -

        Dear Llywelyn,

        Thank you for your input. Before proceeding I'm going to do some derisking with some image ratio code for option 5. I think its best to store the original image and have a resized version for display which is regenerated when the image size changed. Will keep progress on here.

        Progress currently slow as need to finish a few other things first that may help with this.

        Cheers,

        Gareth

        Show
        Gareth J Barnard added a comment - Dear Llywelyn, Thank you for your input. Before proceeding I'm going to do some derisking with some image ratio code for option 5. I think its best to store the original image and have a resized version for display which is regenerated when the image size changed. Will keep progress on here. Progress currently slow as need to finish a few other things first that may help with this. Cheers, Gareth
        Hide
        Derek Chirnside added a comment -

        Any progress on this Gareth?
        -Derek

        Show
        Derek Chirnside added a comment - Any progress on this Gareth? -Derek
        Hide
        Gareth J Barnard added a comment -

        Dear Derek Chirnside,

        To be honest, no. Pragmatically, the funding model proposed and now successfully implemented by Joseph Thibault of Moodle News is now a viable source of fuel for the development time. However, in order to provide a reasonable amount of certainty a good degree of technical de-risking needs to be undertaken to satisfy the requirements. I've not had time to do this whilst I've been working on other projects that have a higher chance of bringing in money.

        Cheers,

        Gareth

        Show
        Gareth J Barnard added a comment - Dear Derek Chirnside , To be honest, no. Pragmatically, the funding model proposed and now successfully implemented by Joseph Thibault of Moodle News is now a viable source of fuel for the development time. However, in order to provide a reasonable amount of certainty a good degree of technical de-risking needs to be undertaken to satisfy the requirements. I've not had time to do this whilst I've been working on other projects that have a higher chance of bringing in money. Cheers, Gareth
        Hide
        Gareth J Barnard added a comment - - edited

        Notes to self:

        1. Extra field in format_grid_icon for scaled image.
        2. Update path of using existing 'imagepath' field in format_grid_icon table as source image.
        3. Mimetype can be repeatedly guessed upon image size change, possibly stored.
        4. Need 'flag' / detection for when setting changes. Use hidden settings?
        5. Have list of widths as multiples of 70 - based upon current 210 as 210 / 3 and 140 / 2 = 3-2 ratio. So sensible sizes: 70, 140, 210, 280, 350, 420, 490 and 560. Possibly consider powers of 2 as well or as replacement (as old 210's would eventually be replaced): (64 - tested = too small), 128, 192, 256, 320, 384, 448, 512, 576, 640, 704 and 768.
        6. Calculate height based upon width and sensible image ratios of: 3-2, 3-1, 3-3, 2-3, 1-3, 4-3 and 3-4.
        7. Store new images as original in 'imagepath'.

        Show
        Gareth J Barnard added a comment - - edited Notes to self: 1. Extra field in format_grid_icon for scaled image. 2. Update path of using existing 'imagepath' field in format_grid_icon table as source image. 3. Mimetype can be repeatedly guessed upon image size change, possibly stored. 4. Need 'flag' / detection for when setting changes. Use hidden settings? 5. Have list of widths as multiples of 70 - based upon current 210 as 210 / 3 and 140 / 2 = 3-2 ratio. So sensible sizes: 70, 140, 210, 280, 350, 420, 490 and 560. Possibly consider powers of 2 as well or as replacement (as old 210's would eventually be replaced): (64 - tested = too small), 128, 192, 256, 320, 384, 448, 512, 576, 640, 704 and 768. 6. Calculate height based upon width and sensible image ratios of: 3-2, 3-1, 3-3, 2-3, 1-3, 4-3 and 3-4. 7. Store new images as original in 'imagepath'.
        Hide
        Gareth J Barnard added a comment - - edited

        Plan to self:

        1. When uploading an image to 'imagepath' perform ratio orientated re-scale to 768px x relative height if image has a width greater than 768px.
        2. Decided to go with familiar powers of '2' sizes for images with the exception of leaving the old '210' in as default setting.
        3. Add new field of 'displayedimagepath' in 'format_grid_icon' table. Going to convert and store the re-scaled image such that large image files are not transmitted saving bandwidth and load time.
        4. On page load if 'imagepath' has a file and 'displayedimagepath' does not then convert with current settings and update 'displayimagepath' - this is really a 'catch' for upgraded courses.
        5. On page load if 'imagepath' does not have a file and 'displayedimagepath' does then remove displayed image from file system.
        6. On upload image with existing 'editimage.php' code then additionally create 'displayedimagepath' version with current settings.
        7. The method 'course_format_options' in 'lib.php' can contain 'hidden' settings which are not displayed on the form (See Collapsed Topics), so have hidden duplicates of the settings the user sees to set the width and ratio so that the method 'update_course_format_options' can determine if something has changed when it gets called. If it has then it can go through each 'imagepath' and regenerate 'displayedimagepath'.
        8. Consider adding 'delete' image at the same time by adding a button and calling "$fs->delete_area_files($context->id, 'course', 'section', $sectionid);" - this as it stands in the code is probably not brilliant as would delete other's images too.
        9. In 'Readme' stipulate that existing courses have had their image re-scaled to 210 x 140 and therefore will look odd at large sizes. Nothing can be done bar re-uploading the image.
        10. Looking at http://docs.moodle.org/dev/File_API will need to prefix the 'displayedimagepath' with something or de-risk to see if the 'filepath' could be something different when creating in 'editimage.php' and serving with 'moodle_url::make_pluginfile_url()' in 'renderer.php'.

        Found on the web from http://ericjuden.com/2009/07/jquery-image-resize/:

        $(document).ready(function() {
            $('.story-small img').each(function() {
                var maxWidth = 100; // Max width for the image
                var maxHeight = 100;    // Max height for the image
                var ratio = 0;  // Used for aspect ratio
                var width = $(this).width();    // Current image width
                var height = $(this).height();  // Current image height
         
                // Check if the current width is larger than the max
                if(width > maxWidth){
                    ratio = maxWidth / width;   // get ratio for scaling image
                    $(this).css("width", maxWidth); // Set new width
                    $(this).css("height", height * ratio);  // Scale height based on ratio
                    height = height * ratio;    // Reset height to match scaled image
                    width = width * ratio;    // Reset width to match scaled image
                }
         
                // Check if current height is larger than max
                if(height > maxHeight){
                    ratio = maxHeight / height; // get ratio for scaling image
                    $(this).css("height", maxHeight);   // Set new height
                    $(this).css("width", width * ratio);    // Scale width based on ratio
                    width = width * ratio;    // Reset width to match scaled image
                }
            });
        });
        

        So could adapt logic.

        Show
        Gareth J Barnard added a comment - - edited Plan to self: When uploading an image to 'imagepath' perform ratio orientated re-scale to 768px x relative height if image has a width greater than 768px. Decided to go with familiar powers of '2' sizes for images with the exception of leaving the old '210' in as default setting. Add new field of 'displayedimagepath' in 'format_grid_icon' table. Going to convert and store the re-scaled image such that large image files are not transmitted saving bandwidth and load time. On page load if 'imagepath' has a file and 'displayedimagepath' does not then convert with current settings and update 'displayimagepath' - this is really a 'catch' for upgraded courses. On page load if 'imagepath' does not have a file and 'displayedimagepath' does then remove displayed image from file system. On upload image with existing 'editimage.php' code then additionally create 'displayedimagepath' version with current settings. The method 'course_format_options' in 'lib.php' can contain 'hidden' settings which are not displayed on the form (See Collapsed Topics), so have hidden duplicates of the settings the user sees to set the width and ratio so that the method 'update_course_format_options' can determine if something has changed when it gets called. If it has then it can go through each 'imagepath' and regenerate 'displayedimagepath'. Consider adding 'delete' image at the same time by adding a button and calling "$fs->delete_area_files($context->id, 'course', 'section', $sectionid);" - this as it stands in the code is probably not brilliant as would delete other's images too. In 'Readme' stipulate that existing courses have had their image re-scaled to 210 x 140 and therefore will look odd at large sizes. Nothing can be done bar re-uploading the image. Looking at http://docs.moodle.org/dev/File_API will need to prefix the 'displayedimagepath' with something or de-risk to see if the 'filepath' could be something different when creating in 'editimage.php' and serving with 'moodle_url::make_pluginfile_url()' in 'renderer.php'. Found on the web from http://ericjuden.com/2009/07/jquery-image-resize/: $(document).ready(function() { $('.story-small img').each(function() { var maxWidth = 100; // Max width for the image var maxHeight = 100; // Max height for the image var ratio = 0; // Used for aspect ratio var width = $( this ).width(); // Current image width var height = $( this ).height(); // Current image height // Check if the current width is larger than the max if (width > maxWidth){ ratio = maxWidth / width; // get ratio for scaling image $( this ).css( "width" , maxWidth); // Set new width $( this ).css( "height" , height * ratio); // Scale height based on ratio height = height * ratio; // Reset height to match scaled image width = width * ratio; // Reset width to match scaled image } // Check if current height is larger than max if (height > maxHeight){ ratio = maxHeight / height; // get ratio for scaling image $( this ).css( "height" , maxHeight); // Set new height $( this ).css( "width" , width * ratio); // Scale width based on ratio width = width * ratio; // Reset width to match scaled image } }); }); So could adapt logic.
        Hide
        Gareth J Barnard added a comment - - edited

        Thought:

        Currently in 'editimage.php' the code is:

                // We have a new file so can delete the old....
                $fs->delete_area_files($context->id, 'course', 'section', $sectionid);
                // Resize the new image and save it...
                $created = time();
                $storedfile_record = array(
                    'contextid' => $contextid,
                    'component' => 'course',
                    'filearea' => 'section',
                    'itemid' => $sectionid,
                    'filepath' => '/',
                    'filename' => $newfilename,
                    'timecreated' => $created,
                    'timemodified' => $created);
        

        And yet in the 'files' table other mods / core bits have their own 'component' / 'filearea' - odd as I wonder why nobody has ever complained about 'course' / 'section' unless it's to do with 'file_pluginfile()' in '/lib/filelib.php' when called from '/pluginfile.php' knowing how to serve the file.

        Ok, given the code in 'file_pluginfile()':

            } else {
                // try to serve general plugin file in arbitrary context
                $dir = get_component_directory($component);
                if (!file_exists("$dir/lib.php")) {
                    send_file_not_found();
                }
                include_once("$dir/lib.php");
        
                $filefunction = $component.'_pluginfile';
                if (function_exists($filefunction)) {
                    // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
                    $filefunction($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
                }
        
                send_file_not_found();
            }
        

        It would look like the format would have to implement it's own serving code in 'lib.php' if the component was 'format_grid' like:

        function theme_shoelace_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
            if ($context->contextlevel == CONTEXT_SYSTEM) {
                if ($filearea === 'logo') {
                   $theme = theme_config::load('shoelace');
                   return $theme->setting_file_serve('logo', $args, $forcedownload, $options);
                } else if ($filearea === 'font') {
                    global $CFG;
                    if (!empty($CFG->themedir)) {
                        $thefontpath = $CFG->themedir . '/shoelace/style/font/';
                    } else {
                        $thefontpath = $CFG->dirroot . '/theme/shoelace/style/font/';
                    }
        
                    // Note: Third parameter is normally 'default' which is the 'lifetime' of the file.  Here set lower for development purposes.
                    send_file($thefontpath.$args[1], $args[1], 20 , 0, false, false, 'font/opentype');
                } else {
                    send_file_not_found();
                }
            } else {
                send_file_not_found();
            }
        }
        

        Which would be anyway the same as in 'file_pluginfile()':

                } else if ($filearea === 'section') {
                    if ($CFG->forcelogin) {
                        require_login($course);
                    } else if ($course->id != SITEID) {
                        require_login($course);
                    }
        
                    $sectionid = (int)array_shift($args);
        
                    if (!$section = $DB->get_record('course_sections', array('id'=>$sectionid, 'course'=>$course->id))) {
                        send_file_not_found();
                    }
        
                    $filename = array_pop($args);
                    $filepath = $args ? '/'.implode('/', $args).'/' : '/';
                    if (!$file = $fs->get_file($context->id, 'course', 'section', $sectionid, $filepath, $filename) or $file->is_directory()) {
                        send_file_not_found();
                    }
        
                    session_get_instance()->write_close(); // unlock session during fileserving
                    send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
        
                } else {
                    send_file_not_found();
                }
        

        And would have to determine the right value of '$context->contextlevel' to check. So, if it's not broken then don't fix it and just adapt 'filepath' for the displayed image. If anybody ever needs the same filename in the root path '/' then would need to somehow upgrade existing courses to use a new path for 'imagefile'.

        Show
        Gareth J Barnard added a comment - - edited Thought: Currently in 'editimage.php' the code is: // We have a new file so can delete the old.... $fs->delete_area_files($context->id, 'course', 'section', $sectionid); // Resize the new image and save it... $created = time(); $storedfile_record = array( 'contextid' => $contextid, 'component' => 'course', 'filearea' => 'section', 'itemid' => $sectionid, 'filepath' => '/', 'filename' => $newfilename, 'timecreated' => $created, 'timemodified' => $created); And yet in the 'files' table other mods / core bits have their own 'component' / 'filearea' - odd as I wonder why nobody has ever complained about 'course' / 'section' unless it's to do with 'file_pluginfile()' in '/lib/filelib.php' when called from '/pluginfile.php' knowing how to serve the file. Ok, given the code in 'file_pluginfile()': } else { // try to serve general plugin file in arbitrary context $dir = get_component_directory($component); if (!file_exists( "$dir/lib.php" )) { send_file_not_found(); } include_once( "$dir/lib.php" ); $filefunction = $component.'_pluginfile'; if (function_exists($filefunction)) { // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found" $filefunction($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview)); } send_file_not_found(); } It would look like the format would have to implement it's own serving code in 'lib.php' if the component was 'format_grid' like: function theme_shoelace_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) { if ($context->contextlevel == CONTEXT_SYSTEM) { if ($filearea === 'logo') { $theme = theme_config::load('shoelace'); return $theme->setting_file_serve('logo', $args, $forcedownload, $options); } else if ($filearea === 'font') { global $CFG; if (!empty($CFG->themedir)) { $thefontpath = $CFG->themedir . '/shoelace/style/font/'; } else { $thefontpath = $CFG->dirroot . '/theme/shoelace/style/font/'; } // Note: Third parameter is normally ' default ' which is the 'lifetime' of the file. Here set lower for development purposes. send_file($thefontpath.$args[1], $args[1], 20 , 0, false , false , 'font/opentype'); } else { send_file_not_found(); } } else { send_file_not_found(); } } Which would be anyway the same as in 'file_pluginfile()': } else if ($filearea === 'section') { if ($CFG->forcelogin) { require_login($course); } else if ($course->id != SITEID) { require_login($course); } $sectionid = ( int )array_shift($args); if (!$section = $DB->get_record('course_sections', array('id'=>$sectionid, 'course'=>$course->id))) { send_file_not_found(); } $filename = array_pop($args); $filepath = $args ? '/'.implode('/', $args).'/' : '/'; if (!$file = $fs->get_file($context->id, 'course', 'section', $sectionid, $filepath, $filename) or $file->is_directory()) { send_file_not_found(); } session_get_instance()->write_close(); // unlock session during fileserving send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview)); } else { send_file_not_found(); } And would have to determine the right value of '$context->contextlevel' to check. So, if it's not broken then don't fix it and just adapt 'filepath' for the displayed image. If anybody ever needs the same filename in the root path '/' then would need to somehow upgrade existing courses to use a new path for 'imagefile'.
        Hide
        Gareth J Barnard added a comment - - edited

        Given 'file_storage.php' has:

            public function delete_area_files($contextid, $component = false, $filearea = false, $itemid = false) {
                global $DB;
        
                $conditions = array('contextid'=>$contextid);
                if ($component !== false) {
                    $conditions['component'] = $component;
                }
                if ($filearea !== false) {
                    $conditions['filearea'] = $filearea;
                }
                if ($itemid !== false) {
                    $conditions['itemid'] = $itemid;
                }
        
                $filerecords = $DB->get_records('files', $conditions);
                foreach ($filerecords as $filerecord) {
                    $this->get_file_instance($filerecord)->delete();
                }
        
                return true; // BC only
            }
        

        Then could have own:

            public function delete_area_files_with_filepath($contextid, $component = false, $filearea = false, $filepath = false, $itemid = false) {
                global $DB;
        
                $fs = get_file_storage();
        
                $conditions = array('contextid'=>$contextid);
                if ($component !== false) {
                    $conditions['component'] = $component;
                }
                if ($filearea !== false) {
                    $conditions['filearea'] = $filearea;
                }
                if ($filepath !== false) {
                    $conditions['filepath'] = $filepath;
                }
                if ($itemid !== false) {
                    $conditions['itemid'] = $itemid;
                }
        
                $filerecords = $DB->get_records('files', $conditions);
                foreach ($filerecords as $filerecord) {
                    $fs->get_file_instance($filerecord)->delete();
                }
        
                return true; // BC only
            }
        

        Then would only remove '/' path files for the section.

        Or better still as the old name is known, then just delete that instead of the whole area, using '$fs->file_exists()' in 'editimage.php' to determine if need to delete. Or test on 'grid_get_icon()' by possibly using 'course_get_format($course)' to get a reference to the 'lib.php' 'format_grid' object that has that method.

        Show
        Gareth J Barnard added a comment - - edited Given 'file_storage.php' has: public function delete_area_files($contextid, $component = false , $filearea = false , $itemid = false ) { global $DB; $conditions = array('contextid'=>$contextid); if ($component !== false ) { $conditions['component'] = $component; } if ($filearea !== false ) { $conditions['filearea'] = $filearea; } if ($itemid !== false ) { $conditions['itemid'] = $itemid; } $filerecords = $DB->get_records('files', $conditions); foreach ($filerecords as $filerecord) { $ this ->get_file_instance($filerecord)->delete(); } return true ; // BC only } Then could have own: public function delete_area_files_with_filepath($contextid, $component = false , $filearea = false , $filepath = false , $itemid = false ) { global $DB; $fs = get_file_storage(); $conditions = array('contextid'=>$contextid); if ($component !== false ) { $conditions['component'] = $component; } if ($filearea !== false ) { $conditions['filearea'] = $filearea; } if ($filepath !== false ) { $conditions['filepath'] = $filepath; } if ($itemid !== false ) { $conditions['itemid'] = $itemid; } $filerecords = $DB->get_records('files', $conditions); foreach ($filerecords as $filerecord) { $fs->get_file_instance($filerecord)->delete(); } return true ; // BC only } Then would only remove '/' path files for the section. Or better still as the old name is known, then just delete that instead of the whole area, using '$fs->file_exists()' in 'editimage.php' to determine if need to delete. Or test on 'grid_get_icon()' by possibly using 'course_get_format($course)' to get a reference to the 'lib.php' 'format_grid' object that has that method.
        Hide
        Gareth J Barnard added a comment -

        Note to self: Refactor use of 'image' to 'icon' in DB etc.

        Show
        Gareth J Barnard added a comment - Note to self: Refactor use of 'image' to 'icon' in DB etc.
        Hide
        Gareth J Barnard added a comment - - edited

        Time estimates (including where appropriate initial testing):

        1. Research = 8 hours = done.
        2. Table changes and refactoring = 2 hours = done.
        3. Icon resizing code with ratio logic and changes to 'editimage.php' = 3 hours.
        4. Settings (including defaults) = 1 hour.
        5. Reset settings for course and all Grid format courses for admins = 1 hour.
        6. Change icon size capability and enforcement = 1 hour.
        7. Adaptive CSS = 1 hour.
        8. Change of setting detection code = 1 hour.
        9. Change the border width and colour, icon background colour, current section colour and current icon colour = 45 mins.
        10. Testing = 5 hours.

        = Approx 18:45 + 5 = 23:45 hours.

        Show
        Gareth J Barnard added a comment - - edited Time estimates (including where appropriate initial testing): Research = 8 hours = done. Table changes and refactoring = 2 hours = done. Icon resizing code with ratio logic and changes to 'editimage.php' = 3 hours. Settings (including defaults) = 1 hour. Reset settings for course and all Grid format courses for admins = 1 hour. Change icon size capability and enforcement = 1 hour. Adaptive CSS = 1 hour. Change of setting detection code = 1 hour. Change the border width and colour, icon background colour, current section colour and current icon colour = 45 mins. Testing = 5 hours. = Approx 18:45 + 5 = 23:45 hours.
        Hide
        Gareth J Barnard added a comment -

        Note: There seems to be an issue with the word 'icon' being used interchangeably with the word 'image' - historical I think. In reality there is just the 'image' and its container. So instead of creating a nightmare scenario of changing every 'icon' to 'image' / 'imagecontainer' I propose going with the latter with this development and phasing in over time changing 'icon' to 'imagecontainer'.

        Show
        Gareth J Barnard added a comment - Note: There seems to be an issue with the word 'icon' being used interchangeably with the word 'image' - historical I think. In reality there is just the 'image' and its container. So instead of creating a nightmare scenario of changing every 'icon' to 'image' / 'imagecontainer' I propose going with the latter with this development and phasing in over time changing 'icon' to 'imagecontainer'.
        Hide
        llywelyn morgan added a comment -

        just watched the youtube video. looks great. can't wait to play with it. i'm sure everybody appreciates the work you've done improving the best course format out there. diolch gareth.

        Show
        llywelyn morgan added a comment - just watched the youtube video. looks great. can't wait to play with it. i'm sure everybody appreciates the work you've done improving the best course format out there. diolch gareth.
        Hide
        Gareth J Barnard added a comment -

        Thanks llywelyn morgan, This is a substantial amount of work and so I'm in the process of sorting crowd funding for it. Given the time taken already and what will be required as against what I will ask for in terms of crowd funding I'm selling it 'cheap' with in effect a 70 - 75% discount on the real cost of the improvement.

        Show
        Gareth J Barnard added a comment - Thanks llywelyn morgan , This is a substantial amount of work and so I'm in the process of sorting crowd funding for it. Given the time taken already and what will be required as against what I will ask for in terms of crowd funding I'm selling it 'cheap' with in effect a 70 - 75% discount on the real cost of the improvement.
        Hide
        Gareth J Barnard added a comment -

        Hi all,

        Crowd funding proposal in place: https://moodle.org/mod/data/view.php?d=90&rid=6321 - please support .

        Cheers,

        Gareth

        Show
        Gareth J Barnard added a comment - Hi all, Crowd funding proposal in place: https://moodle.org/mod/data/view.php?d=90&rid=6321 - please support . Cheers, Gareth
        Hide
        Fred Yankowski added a comment -

        A Testimonial:

        Gareth helped me with a problem upgrading grid-format courses from an old moodle 1.9 system to 2.2. Within a short time he designed, coded, and delivered a complete solution that is working great. He is likely to do a great job with this grid-format enhancement project. Please support him.

        Fred Yankowski
        Application Developer
        Illinois Mathematics and Science Academy

        Show
        Fred Yankowski added a comment - A Testimonial: Gareth helped me with a problem upgrading grid-format courses from an old moodle 1.9 system to 2.2. Within a short time he designed, coded, and delivered a complete solution that is working great. He is likely to do a great job with this grid-format enhancement project. Please support him. Fred Yankowski Application Developer Illinois Mathematics and Science Academy
        Hide
        Gareth J Barnard added a comment -

        Details of the code and how to get are on: https://moodle.org/mod/forum/discuss.php?d=243295

        Show
        Gareth J Barnard added a comment - Details of the code and how to get are on: https://moodle.org/mod/forum/discuss.php?d=243295

          People

          • Votes:
            8 Vote for this issue
            Watchers:
            10 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development